From 8ff7f1374b5c8821172116570455bb1771dfec80 Mon Sep 17 00:00:00 2001 From: Laurent Pugin Date: Wed, 2 Oct 2024 19:01:14 +0200 Subject: [PATCH 01/25] Initial refactoring for using fraction in alignment calculation --- include/vrv/alignfunctor.h | 2 +- include/vrv/calcalignmentxposfunctor.h | 2 +- include/vrv/findlayerelementsfunctor.h | 12 +-- include/vrv/horizontalaligner.h | 76 ++++++++++++--- include/vrv/layer.h | 10 +- include/vrv/layerelement.h | 12 +-- src/alignfunctor.cpp | 14 +-- src/calcalignmentxposfunctor.cpp | 12 +-- src/findlayerelementsfunctor.cpp | 18 ++-- src/horizontalaligner.cpp | 128 +++++++++++++++++++++---- src/iopae.cpp | 2 +- src/layer.cpp | 22 +++-- src/layerelement.cpp | 26 ++--- src/measure.cpp | 4 +- src/midifunctor.cpp | 25 ++--- src/view_element.cpp | 6 +- 16 files changed, 260 insertions(+), 111 deletions(-) diff --git a/include/vrv/alignfunctor.h b/include/vrv/alignfunctor.h index a4fadfef313..2b9aa627331 100644 --- a/include/vrv/alignfunctor.h +++ b/include/vrv/alignfunctor.h @@ -75,7 +75,7 @@ class AlignHorizontallyFunctor : public DocFunctor { // The measureAligner MeasureAligner *m_measureAligner; // The time - double m_time; + Fraction m_time; // The current MeterSig, Mensur and Proport AlignMeterParams m_currentParams; // The current notation type diff --git a/include/vrv/calcalignmentxposfunctor.h b/include/vrv/calcalignmentxposfunctor.h index cce4a6e6ac4..5eda96449a8 100644 --- a/include/vrv/calcalignmentxposfunctor.h +++ b/include/vrv/calcalignmentxposfunctor.h @@ -61,7 +61,7 @@ class CalcAlignmentXPosFunctor : public DocFunctor { // private: // The previous time position - double m_previousTime; + Fraction m_previousTime; // The previous x rel position int m_previousXRel; // Duration of the longest note diff --git a/include/vrv/findlayerelementsfunctor.h b/include/vrv/findlayerelementsfunctor.h index 8d1ec87b1a1..7bdf1eeb657 100644 --- a/include/vrv/findlayerelementsfunctor.h +++ b/include/vrv/findlayerelementsfunctor.h @@ -41,7 +41,7 @@ class LayersInTimeSpanFunctor : public ConstFunctor { /* * Set the time and duration of the event */ - void SetEvent(double time, double duration); + void SetEvent(const Fraction &time, const Fraction &duration); /* * Retrieve the search result @@ -65,9 +65,9 @@ class LayersInTimeSpanFunctor : public ConstFunctor { // private: // The time of the event - double m_time; + Fraction m_time; // The duration of the event - double m_duration; + Fraction m_duration; // The layers (layerN) found std::set m_layers; // The current time alignment parameters @@ -99,7 +99,7 @@ class LayerElementsInTimeSpanFunctor : public ConstFunctor { /* * Set the time and duration of the event */ - void SetEvent(double time, double duration); + void SetEvent(const Fraction &time, const Fraction &duration); /* * Consider all layers except the current one @@ -126,9 +126,9 @@ class LayerElementsInTimeSpanFunctor : public ConstFunctor { // private: // The time of the event - double m_time; + Fraction m_time; // The duration of the event - double m_duration; + Fraction m_duration; // The list of layer elements found ListOfConstObjects m_elements; // The current time alignment parameters diff --git a/include/vrv/horizontalaligner.h b/include/vrv/horizontalaligner.h index 73f8e09c03d..ff6a97da218 100644 --- a/include/vrv/horizontalaligner.h +++ b/include/vrv/horizontalaligner.h @@ -12,6 +12,8 @@ #include "object.h" #include "vrv.h" +#include + namespace vrv { class Accid; @@ -60,6 +62,53 @@ enum AlignmentType { #define BARLINE_REFERENCES -1 #define TSTAMP_REFERENCES -2 +//---------------------------------------------------------------------------- +// Fraction +//---------------------------------------------------------------------------- + +class Fraction { + +public: + // Constructors + Fraction(int num = 0, int denom = 1); + + /** Addition operator */ + Fraction operator+(const Fraction &other) const; + /** Subtraction operator */ + Fraction operator-(const Fraction &other) const; + /** Multiplication operator */ + Fraction operator*(const Fraction &other) const; + /** Division operator */ + Fraction operator/(const Fraction &other) const; + + /** Equality operator */ + bool operator==(const Fraction &other) const; + /** Less than operator */ + bool operator<(const Fraction &other) const; + /** Less than or equal operator */ + bool operator<=(const Fraction &other) const; + /** Greater than operator */ + bool operator>(const Fraction &other) const; + /** Greater than or equal operator */ + bool operator>=(const Fraction &other) const; + + /** Convert fraction to a double */ + double ToDouble() const; + + /** Convert fraction to a string */ + std::string ToString() const; + +private: + /** Reduce the fraction */ + void Reduce(); + +public: + // +private: + int m_numerator; + int m_denominator; +}; + //---------------------------------------------------------------------------- // Alignment //---------------------------------------------------------------------------- @@ -75,7 +124,7 @@ class Alignment : public Object { */ ///@{ Alignment(); - Alignment(double time, AlignmentType type = ALIGNMENT_DEFAULT); + Alignment(const Fraction &time, AlignmentType type = ALIGNMENT_DEFAULT); virtual ~Alignment(); void Reset() override; ///@} @@ -102,8 +151,8 @@ class Alignment : public Object { * @name Set and get the time value of the alignment */ ///@{ - void SetTime(double time) { m_time = time; } - double GetTime() const { return m_time; } + void SetTime(const Fraction &time) { m_time = time; } + Fraction GetTime() const { return m_time; } ///@} /** @@ -188,7 +237,10 @@ class Alignment : public Object { /** * Debug message */ - std::string LogDebugTreeMsg() override { return StringFormat("%d %f", this->GetXRel(), this->GetTime()); } + std::string LogDebugTreeMsg() override + { + return StringFormat("%d %s", this->GetXRel(), this->GetTime().ToString().c_str()); + } //----------------// // Static methods // @@ -210,7 +262,7 @@ class Alignment : public Object { * formula with parameters can come close and has other advantages. */ static int HorizontalSpaceForDuration( - double intervalTime, int maxActualDur, double spacingLinear, double spacingNonLinear); + const Fraction &intervalTime, int maxActualDur, double spacingLinear, double spacingNonLinear); //----------// // Functors // @@ -247,7 +299,7 @@ class Alignment : public Object { * Stores the time at which the alignment occur. * It is set by the AlignHorizontallyFunctor. */ - double m_time; + Fraction m_time; /** * Defines the type of alignment (see the AlignmentType enum). * We have different types because we want some events occuring at the same @@ -384,8 +436,8 @@ class HorizontalAligner : public Object { * If not, return in idx the position where it needs to be inserted (-1 if it is the end) */ ///@{ - Alignment *SearchAlignmentAtTime(double time, AlignmentType type, int &idx); - const Alignment *SearchAlignmentAtTime(double time, AlignmentType type, int &idx) const; + Alignment *SearchAlignmentAtTime(const Fraction &time, AlignmentType type, int &idx); + const Alignment *SearchAlignmentAtTime(const Fraction &time, AlignmentType type, int &idx) const; ///@} /** @@ -430,19 +482,19 @@ class MeasureAligner : public HorizontalAligner { * The alignment object is added if not found. * The maximum time position is also adjusted accordingly for end barline positioning */ - Alignment *GetAlignmentAtTime(double time, AlignmentType type); + Alignment *GetAlignmentAtTime(const Fraction &time, AlignmentType type); /** * Keep the maximum time of the measure. * This corresponds to the whole duration of the measure and * should be the same for all staves/layers. */ - void SetMaxTime(double time); + void SetMaxTime(const Fraction &time); /** * Return the max time of the measure (i.e., the right measure alignment time) */ - double GetMaxTime() const; + Fraction GetMaxTime() const; /** * @name Set and Get the non-justifiable margin (right and left scoreDefs) @@ -569,7 +621,7 @@ class GraceAligner : public HorizontalAligner { * Retrieve the alignmnet of the type at that time. * The alignment object is added if not found. */ - Alignment *GetAlignmentAtTime(double time, AlignmentType type); + Alignment *GetAlignmentAtTime(const Fraction &time, AlignmentType type); /** * Because the grace notes appear from left to right but need to be aligned diff --git a/include/vrv/layer.h b/include/vrv/layer.h index 45fefba99a1..c450619d864 100644 --- a/include/vrv/layer.h +++ b/include/vrv/layer.h @@ -130,8 +130,10 @@ class Layer : public Object, * Takes into account cross-staff situations: cross staff layers have negative N. */ ///@{ - std::set GetLayersNInTimeSpan(double time, double duration, const Measure *measure, int staff) const; - int GetLayerCountInTimeSpan(double time, double duration, const Measure *measure, int staff) const; + std::set GetLayersNInTimeSpan( + const Fraction &time, const Fraction &duration, const Measure *measure, int staff) const; + int GetLayerCountInTimeSpan( + const Fraction &time, const Fraction &duration, const Measure *measure, int staff) const; ///@} /** @@ -150,9 +152,9 @@ class Layer : public Object, */ ///@{ ListOfObjects GetLayerElementsInTimeSpan( - double time, double duration, const Measure *measure, int staff, bool excludeCurrent); + const Fraction &time, const Fraction &duration, const Measure *measure, int staff, bool excludeCurrent); ListOfConstObjects GetLayerElementsInTimeSpan( - double time, double duration, const Measure *measure, int staff, bool excludeCurrent) const; + const Fraction &time, const Fraction &duration, const Measure *measure, int staff, bool excludeCurrent) const; ///@} /** diff --git a/include/vrv/layerelement.h b/include/vrv/layerelement.h index da9cdc01a0e..30f8e1323c1 100644 --- a/include/vrv/layerelement.h +++ b/include/vrv/layerelement.h @@ -14,12 +14,12 @@ #include "atts_shared.h" #include "facsimileinterface.h" +#include "horizontalaligner.h" #include "linkinginterface.h" #include "object.h" namespace vrv { -class Alignment; class Beam; class BeamElementCoord; class FTrem; @@ -262,26 +262,26 @@ class LayerElement : public Object, /** * Return the duration if the element has a DurationInterface. */ - double GetAlignmentDuration(const AlignMeterParams ¶ms, bool notGraceOnly = true, + Fraction GetAlignmentDuration(const AlignMeterParams ¶ms, bool notGraceOnly = true, data_NOTATIONTYPE notationType = NOTATIONTYPE_cmn) const; /** * Return the duration if the element has a DurationInterface. * Shortcut assigning default values for AlignParameter. */ - double GetAlignmentDuration(bool notGraceOnly = true, data_NOTATIONTYPE notationType = NOTATIONTYPE_cmn) const; + Fraction GetAlignmentDuration(bool notGraceOnly = true, data_NOTATIONTYPE notationType = NOTATIONTYPE_cmn) const; /** * Return the duration if the content of the layer element with a @sameas attribute. * Used only on beam, tuplet or ftrem have. */ - double GetSameAsContentAlignmentDuration(const AlignMeterParams ¶ms, bool notGraceOnly = true, + Fraction GetSameAsContentAlignmentDuration(const AlignMeterParams ¶ms, bool notGraceOnly = true, data_NOTATIONTYPE notationType = NOTATIONTYPE_cmn) const; - double GetContentAlignmentDuration(const AlignMeterParams ¶ms, bool notGraceOnly = true, + Fraction GetContentAlignmentDuration(const AlignMeterParams ¶ms, bool notGraceOnly = true, data_NOTATIONTYPE notationType = NOTATIONTYPE_cmn) const; - double GetContentAlignmentDuration( + Fraction GetContentAlignmentDuration( bool notGraceOnly = true, data_NOTATIONTYPE notationType = NOTATIONTYPE_cmn) const; /** diff --git a/src/alignfunctor.cpp b/src/alignfunctor.cpp index 779518f07de..329b8b2b104 100644 --- a/src/alignfunctor.cpp +++ b/src/alignfunctor.cpp @@ -169,15 +169,15 @@ FunctorCode AlignHorizontallyFunctor::VisitLayerElement(LayerElement *layerEleme Alignment *alignment = firstNote->GetAlignment(); layerElement->SetAlignment(alignment); alignment->AddLayerElementRef(layerElement); - double duration = layerElement->GetAlignmentDuration(m_currentParams, true, m_notationType); - m_time += duration; + Fraction duration = layerElement->GetAlignmentDuration(m_currentParams, true, m_notationType); + m_time = m_time + duration; return FUNCTOR_CONTINUE; } } // We do not align these (container). Any other? else if (layerElement->Is({ BEAM, LIGATURE, FTREM, TUPLET })) { - double duration = layerElement->GetSameAsContentAlignmentDuration(m_currentParams, true, m_notationType); - m_time += duration; + Fraction duration = layerElement->GetSameAsContentAlignmentDuration(m_currentParams, true, m_notationType); + m_time = m_time + duration; return FUNCTOR_CONTINUE; } else if (layerElement->Is(BARLINE)) { @@ -304,12 +304,14 @@ FunctorCode AlignHorizontallyFunctor::VisitLayerElement(LayerElement *layerEleme type = ALIGNMENT_GRACENOTE; } - double duration = 0.0; + Fraction duration; // We have already an alignment with grace note children - skip this if (!layerElement->GetAlignment()) { // get the duration of the event duration = layerElement->GetAlignmentDuration(m_currentParams, true, m_notationType); + //LogDebug("duration %s %f", duration.ToString().c_str(), duration.ToDouble()); + // For timestamp, what we get from GetAlignmentDuration is actually the position of the timestamp // So use it as current time - we can do this because the timestamp loop is redirected from the measure // The time will be reset to 0.0 when starting a new layer anyway @@ -350,7 +352,7 @@ FunctorCode AlignHorizontallyFunctor::VisitLayerElement(LayerElement *layerEleme if (!layerElement->Is(TIMESTAMP_ATTR)) { // increase the time position, but only when not a timestamp (it would actually do nothing) - m_time += duration; + m_time = m_time + duration; } return FUNCTOR_CONTINUE; diff --git a/src/calcalignmentxposfunctor.cpp b/src/calcalignmentxposfunctor.cpp index 780c076f5b9..cad0ee57f3d 100644 --- a/src/calcalignmentxposfunctor.cpp +++ b/src/calcalignmentxposfunctor.cpp @@ -36,7 +36,7 @@ FunctorCode CalcAlignmentXPosFunctor::VisitAlignment(Alignment *alignment) if (alignment->GetType() <= ALIGNMENT_MEASURE_LEFT_BARLINE) return FUNCTOR_CONTINUE; int intervalXRel = 0; - double intervalTime = alignment->GetTime() - m_previousTime; + Fraction intervalTime = alignment->GetTime() - m_previousTime; if (alignment->GetType() > ALIGNMENT_MEASURE_RIGHT_BARLINE) { intervalTime = 0.0; @@ -68,22 +68,22 @@ FunctorCode CalcAlignmentXPosFunctor::VisitAlignment(Alignment *alignment) // alignments, then we now need to move them appropriately if (!m_timestamps.empty() && m_lastNonTimestamp) { int startXRel = m_lastNonTimestamp->GetXRel(); - double startTime = m_lastNonTimestamp->GetTime(); - double endTime = alignment->GetTime(); + Fraction startTime = m_lastNonTimestamp->GetTime(); + Fraction endTime = alignment->GetTime(); // We have timestamp alignments between the left barline and the first beat. We need // to use the MeasureAligner::m_initialTstampDur to calculate the time (percentage) position if (m_lastNonTimestamp->GetType() == ALIGNMENT_MEASURE_LEFT_BARLINE) { startTime = m_measureAligner->GetInitialTstampDur(); } // The duration since the last alignment and the current one - double duration = endTime - startTime; + Fraction duration = endTime - startTime; int space = alignment->GetXRel() - m_lastNonTimestamp->GetXRel(); // For each timestamp alignment, move them proportionally to the space we currently have for (auto &tsAlignment : m_timestamps) { // Avoid division by zero (nothing to move with the alignment anyway if (duration == 0.0) break; - double percent = (tsAlignment->GetTime() - startTime) / duration; - tsAlignment->SetXRel(startXRel + space * percent); + Fraction percent = (tsAlignment->GetTime() - startTime) / duration; + tsAlignment->SetXRel(startXRel + space * percent.ToDouble()); } m_timestamps.clear(); } diff --git a/src/findlayerelementsfunctor.cpp b/src/findlayerelementsfunctor.cpp index 8c5b53fe942..0ebba8830fa 100644 --- a/src/findlayerelementsfunctor.cpp +++ b/src/findlayerelementsfunctor.cpp @@ -22,13 +22,11 @@ namespace vrv { LayersInTimeSpanFunctor::LayersInTimeSpanFunctor(const MeterSig *meterSig, const Mensur *mensur) : ConstFunctor() { - m_time = 0.0; - m_duration = 0.0; m_meterParams.meterSig = meterSig; m_meterParams.mensur = mensur; } -void LayersInTimeSpanFunctor::SetEvent(double time, double duration) +void LayersInTimeSpanFunctor::SetEvent(const Fraction &time, const Fraction &duration) { m_time = time; m_duration = duration; @@ -51,15 +49,15 @@ FunctorCode LayersInTimeSpanFunctor::VisitLayerElement(const LayerElement *layer return FUNCTOR_CONTINUE; if (layerElement->Is(NOTE) && layerElement->GetParent()->Is(CHORD)) return FUNCTOR_CONTINUE; - double duration = layerElement->GetAlignmentDuration(m_meterParams); - double time = layerElement->GetAlignment()->GetTime(); + Fraction duration = layerElement->GetAlignmentDuration(m_meterParams); + Fraction time = layerElement->GetAlignment()->GetTime(); // The event is starting after the end of the element - if (time + duration <= m_time) { + if ((time + duration) <= m_time) { return FUNCTOR_CONTINUE; } // The element is starting after the event end - we can stop here - else if (time >= m_time + m_duration) { + else if (time >= (m_time + m_duration)) { return FUNCTOR_STOP; } @@ -100,7 +98,7 @@ LayerElementsInTimeSpanFunctor::LayerElementsInTimeSpanFunctor( m_allLayersButCurrent = false; } -void LayerElementsInTimeSpanFunctor::SetEvent(double time, double duration) +void LayerElementsInTimeSpanFunctor::SetEvent(const Fraction &time, const Fraction &duration) { m_time = time; m_duration = duration; @@ -124,11 +122,11 @@ FunctorCode LayerElementsInTimeSpanFunctor::VisitLayerElement(const LayerElement if (!layerElement->GetDurationInterface() || layerElement->Is({ MSPACE, SPACE })) return FUNCTOR_CONTINUE; - const double duration = !layerElement->GetFirstAncestor(CHORD) + Fraction duration = !layerElement->GetFirstAncestor(CHORD) ? layerElement->GetAlignmentDuration(m_meterParams) : vrv_cast(layerElement->GetFirstAncestor(CHORD))->GetAlignmentDuration(m_meterParams); - const double time = layerElement->GetAlignment()->GetTime(); + Fraction time = layerElement->GetAlignment()->GetTime(); // The event is starting after the end of the element if ((time + duration) <= m_time) return FUNCTOR_CONTINUE; diff --git a/src/horizontalaligner.cpp b/src/horizontalaligner.cpp index f0b86cb2497..b6b2df1fd80 100644 --- a/src/horizontalaligner.cpp +++ b/src/horizontalaligner.cpp @@ -33,6 +33,97 @@ namespace vrv { +//---------------------------------------------------------------------------- +// Fraction +//---------------------------------------------------------------------------- + +Fraction::Fraction(int num, int denom) : m_numerator(num), m_denominator(denom) +{ + if (denom == 0) { + LogDebug("Denominator cannot be zero."); + denom = 1; + } + Reduce(); +} + +Fraction Fraction::operator+(const Fraction &other) const +{ + int num = m_numerator * other.m_denominator + other.m_numerator * m_denominator; + int denom = m_denominator * other.m_denominator; + return Fraction(num, denom); +} + +Fraction Fraction::operator-(const Fraction &other) const +{ + int num = m_numerator * other.m_denominator - other.m_numerator * m_denominator; + int denom = m_denominator * other.m_denominator; + return Fraction(num, denom); +} + +Fraction Fraction::operator*(const Fraction &other) const +{ + int num = m_numerator * other.m_numerator; + int denom = m_denominator * other.m_denominator; + return Fraction(num, denom); +} + +Fraction Fraction::operator/(const Fraction &other) const +{ + if (other.m_numerator == 0) { + LogDebug("Cannot divide by zero."); + return *this; + } + int num = m_numerator * other.m_denominator; + int denom = m_denominator * other.m_numerator; + return Fraction(num, denom); +} + +bool Fraction::operator==(const Fraction &other) const +{ + return (m_numerator == other.m_numerator) && (m_denominator == other.m_denominator); +} + +bool Fraction::operator<(const Fraction &other) const +{ + return m_numerator * other.m_denominator < other.m_numerator * m_denominator; +} + +bool Fraction::operator<=(const Fraction &other) const +{ + return m_numerator * other.m_denominator <= other.m_numerator * m_denominator; +} + +bool Fraction::operator>(const Fraction &other) const +{ + return m_numerator * other.m_denominator > other.m_numerator * m_denominator; +} + +bool Fraction::operator>=(const Fraction &other) const +{ + return m_numerator * other.m_denominator >= other.m_numerator * m_denominator; +} + +double Fraction::ToDouble() const +{ + return static_cast(m_numerator) / m_denominator; +} + +std::string Fraction::ToString() const +{ + return StringFormat("%d/%d", m_numerator, m_denominator); +} + +void Fraction::Reduce() +{ + if (m_denominator < 0) { // Keep the denominator positive + m_numerator = -m_numerator; + m_denominator = -m_denominator; + } + int gcdVal = std::gcd(abs(m_numerator), abs(m_denominator)); + m_numerator /= gcdVal; + m_denominator /= gcdVal; +} + //---------------------------------------------------------------------------- // HorizontalAligner //---------------------------------------------------------------------------- @@ -49,12 +140,12 @@ void HorizontalAligner::Reset() Object::Reset(); } -Alignment *HorizontalAligner::SearchAlignmentAtTime(double time, AlignmentType type, int &idx) +Alignment *HorizontalAligner::SearchAlignmentAtTime(const Fraction &time, AlignmentType type, int &idx) { return const_cast(std::as_const(*this).SearchAlignmentAtTime(time, type, idx)); } -const Alignment *HorizontalAligner::SearchAlignmentAtTime(double time, AlignmentType type, int &idx) const +const Alignment *HorizontalAligner::SearchAlignmentAtTime(const Fraction &time, AlignmentType type, int &idx) const { idx = -1; // the index if we reach the end. const Alignment *alignment = NULL; @@ -63,8 +154,8 @@ const Alignment *HorizontalAligner::SearchAlignmentAtTime(double time, Alignment alignment = vrv_cast(this->GetChild(i)); assert(alignment); - double alignment_time = alignment->GetTime(); - if (AreEqual(alignment_time, time)) { + Fraction alignment_time = alignment->GetTime(); + if (alignment_time == time) { if (alignment->GetType() == type) { return alignment; } @@ -150,10 +241,10 @@ bool MeasureAligner::IsSupportedChild(Object *child) return true; } -Alignment *MeasureAligner::GetAlignmentAtTime(double time, AlignmentType type) +Alignment *MeasureAligner::GetAlignmentAtTime(const Fraction &time, AlignmentType type) { int idx; // the index if we reach the end. - time = durRound(time); + // time = durRound(time); Alignment *alignment = this->SearchAlignmentAtTime(time, type, idx); // we already have a alignment of the type at that time if (alignment != NULL) return alignment; @@ -175,7 +266,7 @@ Alignment *MeasureAligner::GetAlignmentAtTime(double time, AlignmentType type) return newAlignment; } -void MeasureAligner::SetMaxTime(double time) +void MeasureAligner::SetMaxTime(const Fraction &time) { // we have to have a m_rightBarLineAlignment assert(m_rightBarLineAlignment); @@ -194,7 +285,7 @@ void MeasureAligner::SetMaxTime(double time) } } -double MeasureAligner::GetMaxTime() const +Fraction MeasureAligner::GetMaxTime() const { // we have to have a m_rightBarLineAlignment assert(m_rightBarLineAlignment); @@ -360,10 +451,10 @@ void GraceAligner::Reset() m_totalWidth = 0; } -Alignment *GraceAligner::GetAlignmentAtTime(double time, AlignmentType type) +Alignment *GraceAligner::GetAlignmentAtTime(const Fraction &time, AlignmentType type) { int idx; // the index if we reach the end. - time = round(time); + // time = round(time); Alignment *alignment = this->SearchAlignmentAtTime(time, type, idx); // we already have a alignment of the type at that time if (alignment != NULL) return alignment; @@ -392,14 +483,14 @@ void GraceAligner::StackGraceElement(LayerElement *element) void GraceAligner::AlignStack() { - double time = 0.0; + Fraction time; for (int i = (int)m_graceStack.size(); i > 0; --i) { LayerElement *element = vrv_cast(m_graceStack.at(i - 1)); assert(element); // get the duration of the event - double duration = element->GetAlignmentDuration(false); + Fraction duration = element->GetAlignmentDuration(false); // Time goes backward with grace notes - time -= duration; + time = time - duration; Alignment *alignment = this->GetAlignmentAtTime(time, ALIGNMENT_DEFAULT); element->SetGraceAlignment(alignment); @@ -506,7 +597,7 @@ Alignment::Alignment() : Object(ALIGNMENT) this->Reset(); } -Alignment::Alignment(double time, AlignmentType type) : Object(ALIGNMENT) +Alignment::Alignment(const Fraction &time, AlignmentType type) : Object(ALIGNMENT) { this->Reset(); m_time = time; @@ -518,7 +609,7 @@ void Alignment::Reset() Object::Reset(); m_xRel = 0; - m_time = 0.0; + m_time = Fraction(0, 1); m_type = ALIGNMENT_DEFAULT; ClearGraceAligners(); @@ -736,13 +827,14 @@ std::pair Alignment::GetAlignmentTopBottom() const } int Alignment::HorizontalSpaceForDuration( - double intervalTime, int maxActualDur, double spacingLinear, double spacingNonLinear) + const Fraction &intervalTime, int maxActualDur, double spacingLinear, double spacingNonLinear) { + double doubleIntervalTime = intervalTime.ToDouble(); /* If the longest duration interval in the score is longer than semibreve, adjust spacing so that interval gets the space a semibreve would ordinarily get. */ - if (maxActualDur < DUR_1) intervalTime /= pow(2.0, DUR_1 - maxActualDur); + if (maxActualDur < DUR_1) doubleIntervalTime /= pow(2.0, DUR_1 - maxActualDur); - return pow(intervalTime, spacingNonLinear) * spacingLinear * 10.0; // numbers are experimental constants + return pow(doubleIntervalTime, spacingNonLinear) * spacingLinear * 10.0; // numbers are experimental constants } FunctorCode Alignment::Accept(Functor &functor) diff --git a/src/iopae.cpp b/src/iopae.cpp index 7f7cf315322..5aa0bbd3fc8 100644 --- a/src/iopae.cpp +++ b/src/iopae.cpp @@ -521,7 +521,7 @@ void PAEOutput::WriteTuplet(Tuplet *tuplet) Staff *staff = tuplet->GetAncestorStaff(); - double content = tuplet->GetContentAlignmentDuration(true, staff->m_drawingNotationType); + double content = tuplet->GetContentAlignmentDuration(true, staff->m_drawingNotationType).ToDouble(); // content = DUR_MAX / 2^(dur - 2) int tupletDur = (content != 0.0) ? log2(DUR_MAX / content) + 2 : 4; // We should be looking for dotted values diff --git a/src/layer.cpp b/src/layer.cpp index 560e5642bb2..e76afa8c94d 100644 --- a/src/layer.cpp +++ b/src/layer.cpp @@ -351,8 +351,8 @@ data_STEMDIRECTION Layer::GetDrawingStemDir(const ArrayOfBeamElementCoords *coor // We are ignoring cross-staff situation here because this should not be called if we have one const Staff *staff = first->GetAncestorStaff(); - double time = alignmentFirst->GetTime(); - double duration = 0.0; + Fraction time = alignmentFirst->GetTime(); + Fraction duration; // For the sake of counting number of layers consider only current measure. If first and last elements' layers are // different, take only time within current measure to run GetLayerCountInTimeSpan. const Measure *lastMeasure = vrv_cast(last->GetFirstAncestor(MEASURE)); @@ -362,7 +362,7 @@ data_STEMDIRECTION Layer::GetDrawingStemDir(const ArrayOfBeamElementCoords *coor else { duration = measure->m_measureAligner.GetRightAlignment()->GetTime() - time; } - duration = durRound(duration); + // duration = durRound(duration); if (this->GetLayerCountInTimeSpan(time, duration, measure, staff->GetN()) < 2) { return STEMDIRECTION_NONE; @@ -392,7 +392,8 @@ int Layer::GetLayerCountForTimeSpanOf(const LayerElement *element) const return static_cast(this->GetLayersNForTimeSpanOf(element).size()); } -std::set Layer::GetLayersNInTimeSpan(double time, double duration, const Measure *measure, int staff) const +std::set Layer::GetLayersNInTimeSpan( + const Fraction &time, const Fraction &duration, const Measure *measure, int staff) const { assert(measure); @@ -409,7 +410,8 @@ std::set Layer::GetLayersNInTimeSpan(double time, double duration, const Me return layersInTimeSpan.GetLayers(); } -int Layer::GetLayerCountInTimeSpan(double time, double duration, const Measure *measure, int staff) const +int Layer::GetLayerCountInTimeSpan( + const Fraction &time, const Fraction &duration, const Measure *measure, int staff) const { return static_cast(this->GetLayersNInTimeSpan(time, duration, measure, staff).size()); } @@ -430,8 +432,8 @@ ListOfConstObjects Layer::GetLayerElementsForTimeSpanOf(const LayerElement *elem const Measure *measure = vrv_cast(this->GetFirstAncestor(MEASURE)); assert(measure); - double time = 0.0; - double duration = 0.0; + Fraction time; + Fraction duration; const Alignment *alignment = element->GetAlignment(); // Get duration and time if element has alignment if (alignment) { @@ -449,7 +451,7 @@ ListOfConstObjects Layer::GetLayerElementsForTimeSpanOf(const LayerElement *elem if (!first || !last) return {}; time = first->GetAlignment()->GetTime(); - double lastTime = last->GetAlignment()->GetTime(); + Fraction lastTime = last->GetAlignment()->GetTime(); duration = lastTime - time + last->GetAlignmentDuration(); } else { @@ -462,7 +464,7 @@ ListOfConstObjects Layer::GetLayerElementsForTimeSpanOf(const LayerElement *elem } ListOfObjects Layer::GetLayerElementsInTimeSpan( - double time, double duration, const Measure *measure, int staff, bool excludeCurrent) + const Fraction &time, const Fraction &duration, const Measure *measure, int staff, bool excludeCurrent) { ListOfConstObjects elements = std::as_const(*this).GetLayerElementsInTimeSpan(time, duration, measure, staff, excludeCurrent); @@ -473,7 +475,7 @@ ListOfObjects Layer::GetLayerElementsInTimeSpan( } ListOfConstObjects Layer::GetLayerElementsInTimeSpan( - double time, double duration, const Measure *measure, int staff, bool excludeCurrent) const + const Fraction &time, const Fraction &duration, const Measure *measure, int staff, bool excludeCurrent) const { assert(measure); diff --git a/src/layerelement.cpp b/src/layerelement.cpp index 454c91fd311..d7bd8b4cd16 100644 --- a/src/layerelement.cpp +++ b/src/layerelement.cpp @@ -671,11 +671,11 @@ int LayerElement::GetDrawingRadius(const Doc *doc, bool isInLigature) const return doc->GetGlyphWidth(code, staff->m_drawingStaffSize, this->GetDrawingCueSize()) / 2; } -double LayerElement::GetAlignmentDuration( +Fraction LayerElement::GetAlignmentDuration( const AlignMeterParams ¶ms, bool notGraceOnly, data_NOTATIONTYPE notationType) const { if (this->IsGraceNote() && notGraceOnly) { - return 0.0; + return Fraction(0, 1); } // Only resolve simple sameas links to avoid infinite recursion @@ -719,11 +719,11 @@ double LayerElement::GetAlignmentDuration( return NEUME_SMALL_SPACE; } } - double durationValue = duration->GetInterfaceAlignmentDuration(num, numbase); + Fraction durationValue = duration->GetInterfaceAlignmentDuration(num, numbase); // With fTrem we need to divide the duration by two const FTrem *fTrem = vrv_cast(this->GetFirstAncestor(FTREM, MAX_FTREM_DEPTH)); if (fTrem) { - durationValue /= 2.0; + durationValue = durationValue * Fraction(1, 2); } return durationValue; } @@ -763,11 +763,11 @@ double LayerElement::GetAlignmentDuration( return (syllable->GetLast() == this) ? NEUME_MEDIUM_SPACE : NEUME_SMALL_SPACE; } else { - return 0.0; + return Fraction(0, 1); } } -double LayerElement::GetAlignmentDuration(bool notGraceOnly, data_NOTATIONTYPE notationType) const +Fraction LayerElement::GetAlignmentDuration(bool notGraceOnly, data_NOTATIONTYPE notationType) const { AlignMeterParams params; params.meterSig = NULL; @@ -775,11 +775,11 @@ double LayerElement::GetAlignmentDuration(bool notGraceOnly, data_NOTATIONTYPE n return this->GetAlignmentDuration(params, notGraceOnly, notationType); } -double LayerElement::GetSameAsContentAlignmentDuration( +Fraction LayerElement::GetSameAsContentAlignmentDuration( const AlignMeterParams ¶ms, bool notGraceOnly, data_NOTATIONTYPE notationType) const { if (!this->HasSameasLink() || !this->GetSameasLink()->Is({ BEAM, FTREM, TUPLET })) { - return 0.0; + return Fraction(0, 1); } const LayerElement *sameas = vrv_cast(this->GetSameasLink()); @@ -788,14 +788,14 @@ double LayerElement::GetSameAsContentAlignmentDuration( return sameas->GetContentAlignmentDuration(params, notGraceOnly, notationType); } -double LayerElement::GetContentAlignmentDuration( +Fraction LayerElement::GetContentAlignmentDuration( const AlignMeterParams ¶ms, bool notGraceOnly, data_NOTATIONTYPE notationType) const { if (!this->Is({ BEAM, FTREM, TUPLET })) { - return 0.0; + return Fraction(0, 1); } - double duration = 0.0; + Fraction duration; for (const Object *child : this->GetChildren()) { // Skip everything that does not have a duration interface and notes in chords @@ -804,13 +804,13 @@ double LayerElement::GetContentAlignmentDuration( } const LayerElement *element = vrv_cast(child); assert(element); - duration += element->GetAlignmentDuration(params, notGraceOnly, notationType); + duration = duration + element->GetAlignmentDuration(params, notGraceOnly, notationType); } return duration; } -double LayerElement::GetContentAlignmentDuration(bool notGraceOnly, data_NOTATIONTYPE notationType) const +Fraction LayerElement::GetContentAlignmentDuration(bool notGraceOnly, data_NOTATIONTYPE notationType) const { AlignMeterParams params; params.meterSig = NULL; diff --git a/src/measure.cpp b/src/measure.cpp index 13347082ca6..48bd70e42af 100644 --- a/src/measure.cpp +++ b/src/measure.cpp @@ -475,8 +475,8 @@ const Staff *Measure::GetBottomVisibleStaff() const int Measure::EnclosesTime(int time) const { int repeat = 1; - double timeDuration = m_measureAligner.GetRightAlignment()->GetTime() * static_cast(DURATION_4) / DUR_MAX - * 60.0 / m_currentTempo * 1000.0 + double timeDuration = m_measureAligner.GetRightAlignment()->GetTime().ToDouble() * static_cast(DURATION_4) + / DUR_MAX * 60.0 / m_currentTempo * 1000.0 + 0.5; std::vector::const_iterator iter; for (iter = m_realTimeOffsetMilliseconds.begin(); iter != m_realTimeOffsetMilliseconds.end(); ++iter) { diff --git a/src/midifunctor.cpp b/src/midifunctor.cpp index 05f91a550da..45ea551835c 100644 --- a/src/midifunctor.cpp +++ b/src/midifunctor.cpp @@ -54,7 +54,7 @@ FunctorCode InitOnsetOffsetFunctor::VisitChordEnd(Chord *chord) { LayerElement *element = chord->ThisOrSameasLink(); - double incrementScoreTime = element->GetAlignmentDuration(m_meterParams, true, m_notationType); + double incrementScoreTime = element->GetAlignmentDuration(m_meterParams, true, m_notationType).ToDouble(); incrementScoreTime = incrementScoreTime / (DUR_MAX / DURATION_4); double realTimeIncrementSeconds = incrementScoreTime * 60.0 / m_currentTempo; @@ -84,7 +84,7 @@ FunctorCode InitOnsetOffsetFunctor::VisitLayerElement(LayerElement *layerElement double incrementScoreTime; if (element->Is(REST) || element->Is(SPACE)) { - incrementScoreTime = element->GetAlignmentDuration(m_meterParams, true, m_notationType); + incrementScoreTime = element->GetAlignmentDuration(m_meterParams, true, m_notationType).ToDouble(); incrementScoreTime = incrementScoreTime / (DUR_MAX / DURATION_4); // For rests to be possibly added to the timemap if (element->Is(REST)) { @@ -111,13 +111,13 @@ FunctorCode InitOnsetOffsetFunctor::VisitLayerElement(LayerElement *layerElement // If the note has a @dur or a @dur.ges, take it into account // This means that overwriting only @dots or @dots.ges will not be taken into account if (chord && !note->HasDur() && !note->HasDurGes()) { - incrementScoreTime = chord->GetAlignmentDuration(m_meterParams, true, m_notationType); + incrementScoreTime = chord->GetAlignmentDuration(m_meterParams, true, m_notationType).ToDouble(); } else if (tabGrp && !note->HasDur() && !note->HasDurGes()) { - incrementScoreTime = tabGrp->GetAlignmentDuration(m_meterParams, true, m_notationType); + incrementScoreTime = tabGrp->GetAlignmentDuration(m_meterParams, true, m_notationType).ToDouble(); } else { - incrementScoreTime = note->GetAlignmentDuration(m_meterParams, true, m_notationType); + incrementScoreTime = note->GetAlignmentDuration(m_meterParams, true, m_notationType).ToDouble(); } incrementScoreTime = incrementScoreTime / (DUR_MAX / DURATION_4); double realTimeIncrementSeconds = incrementScoreTime * 60.0 / m_currentTempo; @@ -145,14 +145,15 @@ FunctorCode InitOnsetOffsetFunctor::VisitLayerElement(LayerElement *layerElement BeatRpt *rpt = vrv_cast(element); assert(rpt); - incrementScoreTime = rpt->GetAlignmentDuration(m_meterParams, true, m_notationType); + incrementScoreTime = rpt->GetAlignmentDuration(m_meterParams, true, m_notationType).ToDouble(); incrementScoreTime = incrementScoreTime / (DUR_MAX / DURATION_4); rpt->SetScoreTimeOnset(m_currentScoreTime); m_currentScoreTime += incrementScoreTime; m_currentRealTimeSeconds += incrementScoreTime * 60.0 / m_currentTempo; } else if (layerElement->Is({ BEAM, LIGATURE, FTREM, TUPLET }) && layerElement->HasSameasLink()) { - incrementScoreTime = layerElement->GetSameAsContentAlignmentDuration(m_meterParams, true, m_notationType); + incrementScoreTime + = layerElement->GetSameAsContentAlignmentDuration(m_meterParams, true, m_notationType).ToDouble(); incrementScoreTime = incrementScoreTime / (DUR_MAX / DURATION_4); m_currentScoreTime += incrementScoreTime; m_currentRealTimeSeconds += incrementScoreTime * 60.0 / m_currentTempo; @@ -188,7 +189,7 @@ FunctorCode InitOnsetOffsetFunctor::VisitTabGrpEnd(TabGrp *tabGrp) { LayerElement *element = tabGrp->ThisOrSameasLink(); - double incrementScoreTime = element->GetAlignmentDuration(m_meterParams, true, m_notationType); + double incrementScoreTime = element->GetAlignmentDuration(m_meterParams, true, m_notationType).ToDouble(); incrementScoreTime = incrementScoreTime / (DUR_MAX / DURATION_4); double realTimeIncrementSeconds = incrementScoreTime * 60.0 / m_currentTempo; @@ -238,8 +239,8 @@ FunctorCode InitMaxMeasureDurationFunctor::VisitMeasureEnd(Measure *measure) const double tempo = this->GetAdjustedTempo(); measure->SetCurrentTempo(tempo); - const double scoreTimeIncrement = measure->m_measureAligner.GetRightAlignment()->GetTime() * m_multiRestFactor - * static_cast(DURATION_4) / DUR_MAX; + const double scoreTimeIncrement = measure->m_measureAligner.GetRightAlignment()->GetTime().ToDouble() + * m_multiRestFactor * static_cast(DURATION_4) / DUR_MAX; m_currentScoreTime += scoreTimeIncrement; m_currentRealTimeSeconds += scoreTimeIncrement * 60.0 / tempo; m_multiRestFactor = 1; @@ -362,7 +363,7 @@ FunctorCode GenerateMIDIFunctor::VisitBeatRpt(const BeatRpt *beatRpt) { // Sameas not taken into account for now AlignMeterParams params; - double beatLength = beatRpt->GetAlignmentDuration(params) / (DUR_MAX / DURATION_4); + double beatLength = beatRpt->GetAlignmentDuration(params).ToDouble() / (DUR_MAX / DURATION_4); double startTime = m_totalTime + beatRpt->GetScoreTimeOnset(); int tpq = m_midiFile->getTPQ(); @@ -702,7 +703,7 @@ FunctorCode GenerateMIDIFunctor::VisitPedal(const Pedal *pedal) { if (!pedal->HasDir()) return FUNCTOR_CONTINUE; - double pedalTime = pedal->GetStart()->GetAlignment()->GetTime() * static_cast(DURATION_4) / DUR_MAX; + double pedalTime = pedal->GetStart()->GetAlignment()->GetTime().ToDouble() * static_cast(DURATION_4) / DUR_MAX; double startTime = m_totalTime + pedalTime; int tpq = m_midiFile->getTPQ(); diff --git a/src/view_element.cpp b/src/view_element.cpp index 325723616c7..ee980ff0d13 100644 --- a/src/view_element.cpp +++ b/src/view_element.cpp @@ -1165,11 +1165,11 @@ void View::DrawMRest(DeviceContext *dc, LayerElement *element, Layer *layer, Sta const bool drawingCueSize = mRest->GetDrawingCueSize(); int x = mRest->GetDrawingX(); - int y = (measure->m_measureAligner.GetMaxTime() >= (DUR_MAX * 2)) + int y = (measure->m_measureAligner.GetMaxTime().ToDouble() >= (DUR_MAX * 2)) ? element->GetDrawingY() - m_doc->GetDrawingDoubleUnit(staffSize) : element->GetDrawingY(); - char32_t rest - = (measure->m_measureAligner.GetMaxTime() >= (DUR_MAX * 2)) ? SMUFL_E4E2_restDoubleWhole : SMUFL_E4E3_restWhole; + char32_t rest = (measure->m_measureAligner.GetMaxTime().ToDouble() >= (DUR_MAX * 2)) ? SMUFL_E4E2_restDoubleWhole + : SMUFL_E4E3_restWhole; x -= m_doc->GetGlyphWidth(rest, staffSize, drawingCueSize) / 2; From 6ad621cd34d3c883cc5c1f8184ba3b0f450bfb3f Mon Sep 17 00:00:00 2001 From: Laurent Pugin Date: Wed, 2 Oct 2024 19:33:51 +0200 Subject: [PATCH 02/25] Formatting --- src/alignfunctor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/alignfunctor.cpp b/src/alignfunctor.cpp index 329b8b2b104..fad1c8874f4 100644 --- a/src/alignfunctor.cpp +++ b/src/alignfunctor.cpp @@ -310,7 +310,7 @@ FunctorCode AlignHorizontallyFunctor::VisitLayerElement(LayerElement *layerEleme // get the duration of the event duration = layerElement->GetAlignmentDuration(m_currentParams, true, m_notationType); - //LogDebug("duration %s %f", duration.ToString().c_str(), duration.ToDouble()); + // LogDebug("duration %s %f", duration.ToString().c_str(), duration.ToDouble()); // For timestamp, what we get from GetAlignmentDuration is actually the position of the timestamp // So use it as current time - we can do this because the timestamp loop is redirected from the measure From 9f78a063e403111839e7d15bb2136226840b4556 Mon Sep 17 00:00:00 2001 From: Laurent Pugin Date: Thu, 3 Oct 2024 12:44:36 +0200 Subject: [PATCH 03/25] Change additional time variable to Fraction --- include/vrv/durationinterface.h | 7 ++++--- include/vrv/horizontalaligner.h | 2 -- src/durationinterface.cpp | 6 +++--- src/horizontalaligner.cpp | 1 + 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/include/vrv/durationinterface.h b/include/vrv/durationinterface.h index 17d0ec0cc22..bf6b9f3b4b2 100644 --- a/include/vrv/durationinterface.h +++ b/include/vrv/durationinterface.h @@ -12,6 +12,7 @@ #include "atts_gestural.h" #include "atts_mensural.h" #include "atts_shared.h" +#include "horizontalaligner.h" #include "interface.h" namespace vrv { @@ -57,12 +58,12 @@ class DurationInterface : public Interface, ///@} /** - * Returns the duration (in double) for the element. - * It returns 0.0 for grace notes. + * Returns the duration (in Fraction) for the element. + * It returns 0/1 for grace notes. * Careful: this method is not overriding LayerElement::GetAlignmentDuration since * LayerElement and DurationInterface have no inheritance link. */ - double GetInterfaceAlignmentDuration(int num, int numBase) const; + Fraction GetInterfaceAlignmentDuration(int num, int numBase) const; /** * Returns the duration (in double) for the element for mensural notation diff --git a/include/vrv/horizontalaligner.h b/include/vrv/horizontalaligner.h index ff6a97da218..efa5a210895 100644 --- a/include/vrv/horizontalaligner.h +++ b/include/vrv/horizontalaligner.h @@ -12,8 +12,6 @@ #include "object.h" #include "vrv.h" -#include - namespace vrv { class Accid; diff --git a/src/durationinterface.cpp b/src/durationinterface.cpp index 27c4ec698e0..c0b526a5e22 100644 --- a/src/durationinterface.cpp +++ b/src/durationinterface.cpp @@ -72,7 +72,7 @@ void DurationInterface::Reset() m_scoreTimeTiedDuration = 0.0; } -double DurationInterface::GetInterfaceAlignmentDuration(int num, int numBase) const +Fraction DurationInterface::GetInterfaceAlignmentDuration(int num, int numBase) const { int noteDur = this->GetDurGes() != DURATION_NONE ? this->GetActualDurGes() : this->GetActualDur(); if (noteDur == DUR_NONE) noteDur = DUR_4; @@ -80,11 +80,11 @@ double DurationInterface::GetInterfaceAlignmentDuration(int num, int numBase) co if (this->HasNum()) num *= this->GetNum(); if (this->HasNumbase()) numBase *= this->GetNumbase(); - double duration = DUR_MAX / pow(2.0, (double)(noteDur - 2.0)) * numBase / num; + Fraction duration = DUR_MAX / pow(2.0, (double)(noteDur - 2.0)) * numBase / num; int noteDots = (this->HasDotsGes()) ? this->GetDotsGes() : this->GetDots(); if (noteDots != VRV_UNSET) { - duration = 2 * duration - (duration / pow(2, noteDots)); + duration = duration * 2 - (duration / pow(2, noteDots)); } // LogDebug("Duration %d; Dot %d; Alignment %f", noteDur, this->GetDots(), duration); return duration; diff --git a/src/horizontalaligner.cpp b/src/horizontalaligner.cpp index b6b2df1fd80..5d7371f9044 100644 --- a/src/horizontalaligner.cpp +++ b/src/horizontalaligner.cpp @@ -11,6 +11,7 @@ #include #include +#include //---------------------------------------------------------------------------- From 45acb3a8ccc46ae646f4b1d67bc5c8aa35a1becd Mon Sep 17 00:00:00 2001 From: Laurent Pugin Date: Thu, 3 Oct 2024 14:03:31 +0200 Subject: [PATCH 04/25] Remove unnecessary duration defined values --- include/vrv/durationinterface.h | 2 +- libmei/addons/attdef.h | 19 +-- src/adjustbeamsfunctor.cpp | 7 +- src/adjustxposfunctor.cpp | 4 +- src/beam.cpp | 51 ++++---- src/btrem.cpp | 4 +- src/calcalignmentpitchposfunctor.cpp | 6 +- src/calcdotsfunctor.cpp | 18 +-- src/calcligatureorneumeposfunctor.cpp | 22 ++-- src/calcstemfunctor.cpp | 18 +-- src/drawinginterface.cpp | 4 +- src/durationinterface.cpp | 16 +-- src/horizontalaligner.cpp | 2 +- src/iopae.cpp | 20 +-- src/layerelement.cpp | 32 ++--- src/note.cpp | 26 ++-- src/page.cpp | 2 +- src/preparedatafunctor.cpp | 14 +-- src/rest.cpp | 172 ++++++++++++++------------ src/view_beam.cpp | 14 +-- src/view_element.cpp | 25 ++-- src/view_mensural.cpp | 14 +-- src/view_tab.cpp | 22 ++-- 23 files changed, 263 insertions(+), 251 deletions(-) diff --git a/include/vrv/durationinterface.h b/include/vrv/durationinterface.h index bf6b9f3b4b2..b52e34d8953 100644 --- a/include/vrv/durationinterface.h +++ b/include/vrv/durationinterface.h @@ -85,7 +85,7 @@ class DurationInterface : public Interface, /** * @name Return the actual (gestural) duration of the note, for both CMN and mensural durations * See data_DURATION - * For CMN, it is the same (DURATION_1 == DUR_1) + * For CMN, it is the same (DURATION_1 == DURATION_1) * For mensural, we need to apply the DUR_MENSURAL_MASK */ ///@{ diff --git a/libmei/addons/attdef.h b/libmei/addons/attdef.h index fd991b11345..d04af822ac6 100644 --- a/libmei/addons/attdef.h +++ b/libmei/addons/attdef.h @@ -39,19 +39,6 @@ typedef double data_VU; */ #define DUR_NONE -32 #define DUR_MX -1 // maxima -#define DUR_LG 0 // longa -#define DUR_BR 1 // brevis -#define DUR_1 2 // whole note (semibrevis) -#define DUR_2 3 // half note (minima) -#define DUR_4 4 // ... -#define DUR_8 5 -#define DUR_16 6 -#define DUR_32 7 -#define DUR_64 8 -#define DUR_128 9 -#define DUR_256 10 -#define DUR_512 11 -#define DUR_1024 12 // this is it for now // used for alignement #define DUR_MAX 1024 // mensural duration @@ -102,7 +89,8 @@ typedef std::vector> data_BULGE; */ enum data_DURATION { DURATION_NONE = DUR_NONE, - DURATION_long = DUR_LG, + DURATION_maxima = DUR_MX, + DURATION_long, DURATION_breve, DURATION_1, DURATION_2, @@ -116,8 +104,7 @@ enum data_DURATION { DURATION_512, DURATION_1024, DURATION_2048, - DURATION_maxima = DUR_MX, - DURATION_longa = DUR_MENSURAL_OFFSET + DUR_LG, + DURATION_longa = DUR_MENSURAL_OFFSET + DURATION_long, DURATION_brevis, DURATION_semibrevis, DURATION_minima, diff --git a/src/adjustbeamsfunctor.cpp b/src/adjustbeamsfunctor.cpp index c887831d837..86c2f41b524 100644 --- a/src/adjustbeamsfunctor.cpp +++ b/src/adjustbeamsfunctor.cpp @@ -69,7 +69,8 @@ FunctorCode AdjustBeamsFunctor::VisitBeam(Beam *beam) } int leftMargin = 0, rightMargin = 0; - const int beamCount = m_outerBeam->GetBeamPartDuration((*beamSegment.m_beamElementCoordRefs.begin())->m_x) - DUR_8; + const int beamCount + = m_outerBeam->GetBeamPartDuration((*beamSegment.m_beamElementCoordRefs.begin())->m_x) - DURATION_8; const int currentBeamYLeft = m_y1 + m_beamSlope * ((*beamSegment.m_beamElementCoordRefs.begin())->m_x - m_x1); const int currentBeamYRight = m_y1 + m_beamSlope * (beamSegment.m_beamElementCoordRefs.back()->m_x - m_x1); leftMargin = (*beamSegment.m_beamElementCoordRefs.begin())->m_yBeam - currentBeamYLeft @@ -130,7 +131,7 @@ FunctorCode AdjustBeamsFunctor::VisitClef(Clef *clef) Staff *staff = clef->GetAncestorStaff(); // find number of beams at current position - const int beams = m_outerBeam->GetBeamPartDuration(clef) - DUR_4; + const int beams = m_outerBeam->GetBeamPartDuration(clef) - DURATION_4; const int beamWidth = m_outerBeam->m_beamWidth; // find beam Y positions that are relevant to current clef const int currentBeamYLeft = m_y1 + m_beamSlope * (clef->GetContentLeft() - m_x1); @@ -298,7 +299,7 @@ FunctorCode AdjustBeamsFunctor::VisitRest(Rest *rest) if (!m_outerBeam) return FUNCTOR_SIBLINGS; // Calculate possible overlap for the rest with beams - const int beams = m_outerBeam->GetBeamPartDuration(rest, false) - DUR_4; + const int beams = m_outerBeam->GetBeamPartDuration(rest, false) - DURATION_4; const int beamWidth = m_outerBeam->m_beamWidth; const int overlapMargin = rest->Intersects(m_outerBeam, SELF, beams * beamWidth, true) * m_directionBias; diff --git a/src/adjustxposfunctor.cpp b/src/adjustxposfunctor.cpp index 1aa27238bf7..eb923f0a974 100644 --- a/src/adjustxposfunctor.cpp +++ b/src/adjustxposfunctor.cpp @@ -406,8 +406,8 @@ std::pair AdjustXPosFunctor::CalculateXPosOffset(LayerElement *layerEl if (layerElement->Is({ NOTE, CHORD }) && !layerElement->GetFirstAncestor(TUPLET) && bboxElement->Is(REST) && bboxElement->GetFirstAncestor(TUPLET)) { Rest *rest = vrv_cast(bboxElement); - if (rest->GetDur() > DUR_8) { - overlap = 1.5 * (rest->GetDur() - DUR_8) * drawingUnit; + if (rest->GetDur() > DURATION_8) { + overlap = 1.5 * (rest->GetDur() - DURATION_8) * drawingUnit; } } } diff --git a/src/beam.cpp b/src/beam.cpp index 062426112f6..297674fe23a 100644 --- a/src/beam.cpp +++ b/src/beam.cpp @@ -204,7 +204,7 @@ void BeamSegment::CalcSetStemValues(const Staff *staff, const Doc *doc, const Be int stemOffset = 0; const int unit = doc->GetDrawingUnit(staff->m_drawingStaffSize); if (coord->m_partialFlagPlace == coord->m_beamRelativePlace) { - stemOffset = (coord->m_dur - DUR_8) * beamInterface->m_beamWidth; + stemOffset = (coord->m_dur - DURATION_8) * beamInterface->m_beamWidth; } else if (el->GetIsInBeamSpan() && (coord->m_partialFlagPlace != BEAMPLACE_above) && (coord->m_stem->GetDrawingStemDir() == STEMDIRECTION_up)) { @@ -547,7 +547,7 @@ void BeamSegment::AdjustBeamToTremolos(const Doc *doc, const Staff *staff, const if (!stemmedInterface) continue; Stem *stem = stemmedInterface->GetDrawingStem(); - const int offset = (coord->m_dur - DUR_8) * beamInterface->m_beamWidth + beamInterface->m_beamWidthBlack; + const int offset = (coord->m_dur - DURATION_8) * beamInterface->m_beamWidth + beamInterface->m_beamWidthBlack; const int currentAdjustment = stem->CalculateStemModAdjustment(doc, staff, offset); if (std::abs(currentAdjustment) > std::abs(maxAdjustment)) maxAdjustment = currentAdjustment; } @@ -590,7 +590,7 @@ void BeamSegment::CalcBeamInit( beamInterface->m_beamWidthBlack = doc->GetDrawingBeamWidth(staff->m_drawingStaffSize, beamInterface->m_cueSize); beamInterface->m_beamWidthWhite = doc->GetDrawingBeamWhiteWidth(staff->m_drawingStaffSize, beamInterface->m_cueSize); - if (beamInterface->m_shortestDur == DUR_64) { + if (beamInterface->m_shortestDur == DURATION_64) { beamInterface->m_beamWidthWhite *= 4; beamInterface->m_beamWidthWhite /= 3; } @@ -886,7 +886,7 @@ int BeamSegment::CalcBeamSlopeStep( // duration const int dur = beamInterface->m_shortestDur; // Prevent short step with values not shorter than a 16th - if (shortStep && (dur >= DUR_32)) { + if (shortStep && (dur >= DURATION_32)) { step = unit * 2; shortStep = false; } @@ -1002,7 +1002,7 @@ void BeamSegment::CalcAdjustSlope(const Staff *staff, const Doc *doc, BeamDrawin break; } // Here we should look at duration too because longer values in the middle could actually be OK as they are - else if (((coord != m_lastNoteOrChord) || (coord != m_firstNoteOrChord)) && (coord->m_dur > DUR_8)) { + else if (((coord != m_lastNoteOrChord) || (coord != m_firstNoteOrChord)) && (coord->m_dur > DURATION_8)) { const int durLen = len - 0.9 * unit; if (durLen < refLen) { lengthen = true; @@ -1268,9 +1268,9 @@ int BeamSegment::CalcMixedBeamCenterY(int step, int unit) const std::tuple BeamSegment::CalcStemDefiningNote(const Staff *staff, data_BEAMPLACE place) const { - int shortestDuration = DUR_4; + int shortestDuration = DURATION_4; int shortestLoc = VRV_UNSET; - int relevantDuration = DUR_4; + int relevantDuration = DURATION_4; int relevantLoc = VRV_UNSET; const data_STEMDIRECTION globalStemDir = (place == BEAMPLACE_below) ? STEMDIRECTION_down : STEMDIRECTION_up; for (BeamElementCoord *coord : m_beamElementCoordRefs) { @@ -1410,9 +1410,10 @@ void BeamSegment::CalcMixedBeamPlace(const Staff *staff) void BeamSegment::CalcPartialFlagPlace() { - // Start from note that is shorter than DUR_8 - we do not care otherwise, since those do not have additional beams + // Start from note that is shorter than DURATION_8 - we do not care otherwise, since those do not have additional + // beams auto start = std::find_if(m_beamElementCoordRefs.begin(), m_beamElementCoordRefs.end(), - [](BeamElementCoord *coord) { return coord->m_dur >= DUR_16; }); + [](BeamElementCoord *coord) { return coord->m_dur >= DURATION_16; }); if (m_beamElementCoordRefs.end() == start) return; while (start != m_beamElementCoordRefs.end()) { auto subdivision = start; @@ -1426,14 +1427,14 @@ void BeamSegment::CalcPartialFlagPlace() // Find first note longer than 8th or first note that is cross-staff auto found = std::find_if(subdivision, m_beamElementCoordRefs.end(), [&](BeamElementCoord *coord) { if (coord->m_element->Is(REST)) return false; - return ((coord->m_beamRelativePlace != place) || (coord->m_dur <= DUR_8) || (coord->m_breaksec)); + return ((coord->m_beamRelativePlace != place) || (coord->m_dur <= DURATION_8) || (coord->m_breaksec)); }); subdivision = found; // Handle different cases, where we either don't want to proceed (e.g. end of the beam reached) or we want // to process them separately (e.g. on direction change from shorter to longer notes, or vice versa, we do // not want last note of the subdivision to have additional beam, so that it's clearly distinguishable). - if ((m_beamElementCoordRefs.end() == found) || ((*found)->m_dur <= DUR_8)) break; + if ((m_beamElementCoordRefs.end() == found) || ((*found)->m_dur <= DURATION_8)) break; if (((*found)->m_breaksec)) breakSec = true; if ((m_beamElementCoordRefs.end() - 1) == found) { subdivision = m_beamElementCoordRefs.end(); @@ -1467,14 +1468,14 @@ void BeamSegment::CalcSetValues() int BeamSegment::GetAdjacentElementsDuration(int elementX) const { if ((elementX < m_beamElementCoordRefs.front()->m_x) || (elementX > m_beamElementCoordRefs.back()->m_x)) { - return DUR_8; + return DURATION_8; } for (int i = 0; i < int(m_beamElementCoordRefs.size()) - 1; ++i) { if ((m_beamElementCoordRefs.at(i)->m_x < elementX) && (m_beamElementCoordRefs.at(i + 1)->m_x > elementX)) { return std::min(m_beamElementCoordRefs.at(i)->m_dur, m_beamElementCoordRefs.at(i + 1)->m_dur); } } - return DUR_8; + return DURATION_8; } int BeamSegment::GetStartingX() const @@ -1960,7 +1961,7 @@ int BeamElementCoord::CalculateStemLength( const int directionBias = (stemDir == STEMDIRECTION_up) ? 1 : -1; int stemLen = directionBias; // For 8th notes, use the shortened stem (if shortened) - if (preferredDur == DUR_8) { + if (preferredDur == DURATION_8) { if (stemLenInHalfUnits != standardStemLen) { stemLen *= stemLenInHalfUnits; } @@ -1971,13 +1972,13 @@ int BeamElementCoord::CalculateStemLength( else { const bool isOddLength = (extend || !isHorizontal); switch (m_dur) { - case (DUR_16): stemLen *= isOddLength ? 14 : 13; break; - case (DUR_32): stemLen *= isOddLength ? 18 : 16; break; - case (DUR_64): stemLen *= isOddLength ? 22 : 20; break; - case (DUR_128): stemLen *= isOddLength ? 26 : 24; break; - case (DUR_256): stemLen *= isOddLength ? 30 : 28; break; - case (DUR_512): stemLen *= isOddLength ? 34 : 32; break; - case (DUR_1024): stemLen *= isOddLength ? 38 : 36; break; + case (DURATION_16): stemLen *= isOddLength ? 14 : 13; break; + case (DURATION_32): stemLen *= isOddLength ? 18 : 16; break; + case (DURATION_64): stemLen *= isOddLength ? 22 : 20; break; + case (DURATION_128): stemLen *= isOddLength ? 26 : 24; break; + case (DURATION_256): stemLen *= isOddLength ? 30 : 28; break; + case (DURATION_512): stemLen *= isOddLength ? 34 : 32; break; + case (DURATION_1024): stemLen *= isOddLength ? 38 : 36; break; default: stemLen *= 14; } } @@ -2080,8 +2081,8 @@ void BeamElementCoord::UpdateStemLength( std::pair Beam::GetAdditionalBeamCount() const { - int topShortestDur = DUR_8; - int bottomShortestDur = DUR_8; + int topShortestDur = DURATION_8; + int bottomShortestDur = DURATION_8; std::for_each(m_beamElementCoords.begin(), m_beamElementCoords.end(), [&](BeamElementCoord *coord) { if (coord->m_partialFlagPlace == BEAMPLACE_above) { topShortestDur = std::max(topShortestDur, coord->m_dur); @@ -2091,7 +2092,7 @@ std::pair Beam::GetAdditionalBeamCount() const } }); - return { topShortestDur - DUR_8, bottomShortestDur - DUR_8 }; + return { topShortestDur - DURATION_8, bottomShortestDur - DURATION_8 }; } void Beam::SetElementShortening(int shortening) @@ -2109,7 +2110,7 @@ int Beam::GetBeamPartDuration(int x, bool includeRests) const }); // handle cases when coordinate is outside of the beam if (it == m_beamSegment.m_beamElementCoordRefs.end()) { - return DUR_8; + return DURATION_8; } else if (it == m_beamSegment.m_beamElementCoordRefs.begin()) { return (*it)->m_dur; diff --git a/src/btrem.cpp b/src/btrem.cpp index f26464cc33c..97496ef0dcf 100644 --- a/src/btrem.cpp +++ b/src/btrem.cpp @@ -144,11 +144,11 @@ data_STEMMODIFIER BTrem::GetDrawingStemMod() const const int drawingDur = duration->GetActualDur(); if (!this->HasUnitdur()) { - if (drawingDur < DUR_2) return STEMMODIFIER_3slash; + if (drawingDur < DURATION_2) return STEMMODIFIER_3slash; return STEMMODIFIER_NONE; } int slashDur = this->GetUnitdur() - drawingDur; - if (drawingDur < DUR_4) slashDur = this->GetUnitdur() - DUR_4; + if (drawingDur < DURATION_4) slashDur = this->GetUnitdur() - DURATION_4; switch (slashDur) { case 0: return STEMMODIFIER_NONE; case 1: return STEMMODIFIER_1slash; diff --git a/src/calcalignmentpitchposfunctor.cpp b/src/calcalignmentpitchposfunctor.cpp index 188095fc068..b7a95489439 100644 --- a/src/calcalignmentpitchposfunctor.cpp +++ b/src/calcalignmentpitchposfunctor.cpp @@ -169,10 +169,10 @@ FunctorCode CalcAlignmentPitchPosFunctor::VisitLayerElement(LayerElement *layerE // set default location to the middle of the staff Staff *staff = layerElement->GetAncestorStaff(); loc = staff->m_drawingLines - 1; - if ((durInterface->GetDur() < DUR_4) && (loc % 2 != 0)) --loc; + if ((durInterface->GetDur() < DURATION_4) && (loc % 2 != 0)) --loc; // Adjust special cases - if ((durInterface->GetDur() == DUR_1) && (staff->m_drawingLines > 1)) loc += 2; - if ((durInterface->GetDur() == DUR_BR) && (staff->m_drawingLines < 2)) loc -= 2; + if ((durInterface->GetDur() == DURATION_1) && (staff->m_drawingLines > 1)) loc += 2; + if ((durInterface->GetDur() == DURATION_breve) && (staff->m_drawingLines < 2)) loc -= 2; // If within a beam, calculate the rest's height based on it's relationship to the notes that surround it Beam *beam = vrv_cast(layerElement->GetFirstAncestor(BEAM, 1)); diff --git a/src/calcdotsfunctor.cpp b/src/calcdotsfunctor.cpp index 2be321aa7a9..f2bc3cddba8 100644 --- a/src/calcdotsfunctor.cpp +++ b/src/calcdotsfunctor.cpp @@ -80,7 +80,7 @@ FunctorCode CalcDotsFunctor::VisitNote(Note *note) assert(dots); // Stem up, shorter than 4th and not in beam - if ((note->GetDots() > 0) && (m_chordStemDir == STEMDIRECTION_up) && (note->GetDrawingDur() > DUR_4) + if ((note->GetDots() > 0) && (m_chordStemDir == STEMDIRECTION_up) && (note->GetDrawingDur() > DURATION_4) && !note->IsInBeam()) { // Shift according to the flag width if the top note is not flipped if ((note == chord->GetTopNote()) && !note->GetFlippedNotehead()) { @@ -129,7 +129,7 @@ FunctorCode CalcDotsFunctor::VisitRest(Rest *rest) } // Nothing to do - if ((rest->GetDur() <= DUR_BR) || (rest->GetDots() < 1)) { + if ((rest->GetDur() <= DURATION_breve) || (rest->GetDots() < 1)) { return FUNCTOR_SIBLINGS; } @@ -150,12 +150,12 @@ FunctorCode CalcDotsFunctor::VisitRest(Rest *rest) } switch (rest->GetActualDur()) { - case DUR_32: - case DUR_64: loc += 2; break; - case DUR_128: - case DUR_256: loc += 4; break; - case DUR_512: loc += 6; break; - case DUR_1024: loc += 8; break; + case DURATION_32: + case DURATION_64: loc += 2; break; + case DURATION_128: + case DURATION_256: loc += 4; break; + case DURATION_512: loc += 6; break; + case DURATION_1024: loc += 8; break; default: break; } @@ -164,7 +164,7 @@ FunctorCode CalcDotsFunctor::VisitRest(Rest *rest) // HARDCODED int xRel = m_doc->GetDrawingUnit(staffSize) * 2.5; if (drawingCueSize) xRel = m_doc->GetCueSize(xRel); - if (rest->GetDur() > DUR_2) { + if (rest->GetDur() > DURATION_2) { xRel = m_doc->GetGlyphWidth(rest->GetRestGlyph(), staff->m_drawingStaffSize, drawingCueSize); } dots->SetDrawingXRel(std::max(dots->GetDrawingXRel(), xRel)); diff --git a/src/calcligatureorneumeposfunctor.cpp b/src/calcligatureorneumeposfunctor.cpp index efefc3dc3f5..5fb5576ff4f 100644 --- a/src/calcligatureorneumeposfunctor.cpp +++ b/src/calcligatureorneumeposfunctor.cpp @@ -67,18 +67,18 @@ FunctorCode CalcLigatureOrNeumePosFunctor::VisitLigature(Ligature *ligature) // Same treatment for Mx and LG except for positioning, which is done above // We still need to avoid oblique, so keep a flag. bool isMaxima = false; - if (dur1 == DUR_MX) { - dur1 = DUR_LG; + if (dur1 == DURATION_maxima) { + dur1 = DURATION_long; isMaxima = true; } - if (dur2 == DUR_MX) dur2 = DUR_LG; + if (dur2 == DURATION_maxima) dur2 = DURATION_long; int diatonicStep = note->GetDiatonicPitch() - previousNote->GetDiatonicPitch(); bool up = (diatonicStep > 0); bool isLastNote = (note == lastNote); // L - L - if ((dur1 == DUR_LG) && (dur2 == DUR_LG)) { + if ((dur1 == DURATION_long) && (dur2 == DURATION_long)) { if (up) { ligature->m_drawingShapes.at(n1) = LIGATURE_STEM_RIGHT_DOWN; ligature->m_drawingShapes.at(n2) = LIGATURE_STEM_RIGHT_DOWN; @@ -88,7 +88,7 @@ FunctorCode CalcLigatureOrNeumePosFunctor::VisitLigature(Ligature *ligature) } } // L - B - else if ((dur1 == DUR_LG) && (dur2 == DUR_BR)) { + else if ((dur1 == DURATION_long) && (dur2 == DURATION_breve)) { if (up) { ligature->m_drawingShapes.at(n1) = LIGATURE_STEM_RIGHT_DOWN; } @@ -102,7 +102,7 @@ FunctorCode CalcLigatureOrNeumePosFunctor::VisitLigature(Ligature *ligature) } } // B - B - else if ((dur1 == DUR_BR) && (dur2 == DUR_BR)) { + else if ((dur1 == DURATION_breve) && (dur2 == DURATION_breve)) { if (up) { // nothing to change } @@ -119,7 +119,7 @@ FunctorCode CalcLigatureOrNeumePosFunctor::VisitLigature(Ligature *ligature) } } // B - L - else if ((dur1 == DUR_BR) && (dur2 == DUR_LG)) { + else if ((dur1 == DURATION_breve) && (dur2 == DURATION_long)) { if (up) { ligature->m_drawingShapes.at(n2) = LIGATURE_STEM_RIGHT_DOWN; } @@ -133,11 +133,11 @@ FunctorCode CalcLigatureOrNeumePosFunctor::VisitLigature(Ligature *ligature) } } // SB - SB - else if ((dur1 == DUR_1) && (dur2 == DUR_1)) { + else if ((dur1 == DURATION_1) && (dur2 == DURATION_1)) { ligature->m_drawingShapes.at(n1) = LIGATURE_STEM_LEFT_UP; } // SB - L (this should not happen on the first two notes, but this is an encoding problem) - else if ((dur1 == DUR_1) && (dur2 == DUR_LG)) { + else if ((dur1 == DURATION_1) && (dur2 == DURATION_long)) { if (up) { ligature->m_drawingShapes.at(n2) = LIGATURE_STEM_RIGHT_DOWN; } @@ -146,7 +146,7 @@ FunctorCode CalcLigatureOrNeumePosFunctor::VisitLigature(Ligature *ligature) } } // SB - B (this should not happen on the first two notes, but this is an encoding problem) - else if ((dur1 == DUR_1) && (dur2 == DUR_BR)) { + else if ((dur1 == DURATION_1) && (dur2 == DURATION_breve)) { if (up) { // nothing to change } @@ -168,7 +168,7 @@ FunctorCode CalcLigatureOrNeumePosFunctor::VisitLigature(Ligature *ligature) } // With mensural black notation, stack longa going up - if (isLastNote && isMensuralBlack && (dur2 == DUR_LG) && up) { + if (isLastNote && isMensuralBlack && (dur2 == DURATION_long) && up) { // Stack only if at least a third int stackThreshold = 1; // If the previous was going down, adjust the threshold diff --git a/src/calcstemfunctor.cpp b/src/calcstemfunctor.cpp index 36210118578..c5f483ddb31 100644 --- a/src/calcstemfunctor.cpp +++ b/src/calcstemfunctor.cpp @@ -32,7 +32,7 @@ CalcStemFunctor::CalcStemFunctor(Doc *doc) : DocFunctor(doc) { m_chordStemLength = 0; m_verticalCenter = 0; - m_dur = DUR_1; + m_dur = DURATION_1; m_isGraceNote = false; m_isStemSameasSecondary = false; m_tabGrpWithNoNote = false; @@ -348,7 +348,7 @@ FunctorCode CalcStemFunctor::VisitStem(Stem *stem) const bool drawingCueSize = stem->GetDrawingCueSize(); // For notes longer than half notes the stem is always 0 - if (m_dur < DUR_2) { + if (m_dur < DURATION_2) { stem->SetDrawingXRel(0); stem->SetDrawingYRel(0); stem->SetDrawingStemLen(0); @@ -409,7 +409,7 @@ FunctorCode CalcStemFunctor::VisitStem(Stem *stem) int flagOffset = 0; Flag *flag = NULL; // There is never a flag with a duration longer than 8th notes - if (m_dur > DUR_4) { + if (m_dur > DURATION_4) { flag = vrv_cast(stem->GetFirst(FLAG)); assert(flag); // There is never a flag with stem sameas notes @@ -417,7 +417,7 @@ FunctorCode CalcStemFunctor::VisitStem(Stem *stem) flag->m_drawingNbFlags = 0; } else { - flag->m_drawingNbFlags = m_dur - DUR_4; + flag->m_drawingNbFlags = m_dur - DURATION_4; flagOffset = unit * (flag->m_drawingNbFlags + 1); } } @@ -441,7 +441,7 @@ FunctorCode CalcStemFunctor::VisitStem(Stem *stem) int flagHeight = 0; // SMUFL flags cover some additional stem length from the 32th only - if (m_dur > DUR_16) { + if (m_dur > DURATION_16) { assert(flag); Point stemEnd; if (stem->GetDrawingStemDir() == STEMDIRECTION_up) { @@ -450,7 +450,7 @@ FunctorCode CalcStemFunctor::VisitStem(Stem *stem) else { stemEnd = flag->GetStemDownNW(m_doc, staffSize, drawingCueSize); } - // Trick for shortening the stem with DUR_8 + // Trick for shortening the stem with DURATION_8 flagHeight = stemEnd.y; } @@ -496,7 +496,7 @@ FunctorCode CalcStemFunctor::VisitTabDurSym(TabDurSym *tabDurSym) assert(stem); // Do not draw virtual (e.g., whole note) stems - if (m_dur < DUR_2 || m_tabGrpWithNoNote) { + if (m_dur < DURATION_2 || m_tabGrpWithNoNote) { stem->IsVirtual(true); return FUNCTOR_SIBLINGS; } @@ -554,7 +554,7 @@ FunctorCode CalcStemFunctor::VisitTabDurSym(TabDurSym *tabDurSym) int stemSize = tabDurSym->CalcStemLenInThirdUnits(m_staff, stemDir) * m_doc->GetDrawingUnit(staffSize); stemSize /= (3 * stemDirFactor); - if (m_dur == DUR_2) { + if (m_dur == DURATION_2) { // Stems for half notes twice shorter stemSize /= 2; } @@ -565,7 +565,7 @@ FunctorCode CalcStemFunctor::VisitTabDurSym(TabDurSym *tabDurSym) if (m_staff->IsTabGuitar()) { Flag *flag = vrv_cast(stem->GetFirst(FLAG)); if (flag) { - flag->m_drawingNbFlags = m_dur - DUR_4; + flag->m_drawingNbFlags = m_dur - DURATION_4; flag->SetDrawingYRel(-stemSize); } } diff --git a/src/drawinginterface.cpp b/src/drawinginterface.cpp index ebd382c517f..d4be4bf9d35 100644 --- a/src/drawinginterface.cpp +++ b/src/drawinginterface.cpp @@ -108,7 +108,7 @@ void BeamDrawingInterface::Reset() int BeamDrawingInterface::GetTotalBeamWidth() const { - return m_beamWidthBlack + (m_shortestDur - DUR_8) * m_beamWidth; + return m_beamWidthBlack + (m_shortestDur - DURATION_8) * m_beamWidth; } void BeamDrawingInterface::ClearCoords() @@ -459,7 +459,7 @@ bool BeamDrawingInterface::IsRepeatedPattern() const bool BeamDrawingInterface::HasOneStepHeight() const { - if (m_shortestDur < DUR_32) return false; + if (m_shortestDur < DURATION_32) return false; int top = -128; int bottom = 128; diff --git a/src/durationinterface.cpp b/src/durationinterface.cpp index c0b526a5e22..e39fad14f98 100644 --- a/src/durationinterface.cpp +++ b/src/durationinterface.cpp @@ -75,7 +75,7 @@ void DurationInterface::Reset() Fraction DurationInterface::GetInterfaceAlignmentDuration(int num, int numBase) const { int noteDur = this->GetDurGes() != DURATION_NONE ? this->GetActualDurGes() : this->GetActualDur(); - if (noteDur == DUR_NONE) noteDur = DUR_4; + if (noteDur == DUR_NONE) noteDur = DURATION_4; if (this->HasNum()) num *= this->GetNum(); if (this->HasNumbase()) numBase *= this->GetNumbase(); @@ -93,7 +93,7 @@ Fraction DurationInterface::GetInterfaceAlignmentDuration(int num, int numBase) double DurationInterface::GetInterfaceAlignmentMensuralDuration(int num, int numBase, const Mensur *currentMensur) const { int noteDur = this->GetDurGes() != DURATION_NONE ? this->GetActualDurGes() : this->GetActualDur(); - if (noteDur == DUR_NONE) noteDur = DUR_4; + if (noteDur == DUR_NONE) noteDur = DURATION_4; if (!currentMensur) { LogWarning("No current mensur for calculating duration"); @@ -139,14 +139,14 @@ double DurationInterface::GetInterfaceAlignmentMensuralDuration(int num, int num double ratio = 0.0; double duration = (double)DUR_MENSURAL_REF; switch (noteDur) { - case DUR_MX: + case DURATION_maxima: duration *= (double)abs(currentMensur->GetModusminor()) * (double)abs(currentMensur->GetModusmaior()); break; - case DUR_LG: duration *= (double)abs(currentMensur->GetModusminor()); break; - case DUR_BR: break; - case DUR_1: duration /= (double)abs(currentMensur->GetTempus()); break; + case DURATION_long: duration *= (double)abs(currentMensur->GetModusminor()); break; + case DURATION_breve: break; + case DURATION_1: duration /= (double)abs(currentMensur->GetTempus()); break; default: - ratio = pow(2.0, (double)(noteDur - DUR_2)); + ratio = pow(2.0, (double)(noteDur - DURATION_2)); duration /= (double)abs(currentMensur->GetTempus()) * (double)abs(currentMensur->GetProlatio()) * ratio; break; } @@ -190,7 +190,7 @@ int DurationInterface::CalcActualDur(data_DURATION dur) const { if (dur == DURATION_NONE) return DUR_NONE; // maxima (-1) is a mensural only value - if (dur == DURATION_maxima) return DUR_MX; + if (dur == DURATION_maxima) return DURATION_maxima; return (dur & DUR_MENSURAL_MASK); } diff --git a/src/horizontalaligner.cpp b/src/horizontalaligner.cpp index 5d7371f9044..8315fabfaee 100644 --- a/src/horizontalaligner.cpp +++ b/src/horizontalaligner.cpp @@ -833,7 +833,7 @@ int Alignment::HorizontalSpaceForDuration( double doubleIntervalTime = intervalTime.ToDouble(); /* If the longest duration interval in the score is longer than semibreve, adjust spacing so that interval gets the space a semibreve would ordinarily get. */ - if (maxActualDur < DUR_1) doubleIntervalTime /= pow(2.0, DUR_1 - maxActualDur); + if (maxActualDur < DURATION_1) doubleIntervalTime /= pow(2.0, DURATION_1 - maxActualDur); return pow(doubleIntervalTime, spacingNonLinear) * spacingLinear * 10.0; // numbers are experimental constants } diff --git a/src/iopae.cpp b/src/iopae.cpp index 5aa0bbd3fc8..5c654356e48 100644 --- a/src/iopae.cpp +++ b/src/iopae.cpp @@ -528,16 +528,16 @@ void PAEOutput::WriteTuplet(Tuplet *tuplet) std::string dur; switch (tupletDur) { - case (DUR_LG): dur = "0"; break; - case (DUR_BR): dur = "9"; break; - case (DUR_1): dur = "1"; break; - case (DUR_2): dur = "2"; break; - case (DUR_4): dur = "4"; break; - case (DUR_8): dur = "8"; break; - case (DUR_16): dur = "6"; break; - case (DUR_32): dur = "3"; break; - case (DUR_64): dur = "5"; break; - case (DUR_128): dur = "7"; break; + case (DURATION_long): dur = "0"; break; + case (DURATION_breve): dur = "9"; break; + case (DURATION_1): dur = "1"; break; + case (DURATION_2): dur = "2"; break; + case (DURATION_4): dur = "4"; break; + case (DURATION_8): dur = "8"; break; + case (DURATION_16): dur = "6"; break; + case (DURATION_32): dur = "3"; break; + case (DURATION_64): dur = "5"; break; + case (DURATION_128): dur = "7"; break; default: LogWarning("Unsupported tuplet duration"); dur = "4"; } diff --git a/src/layerelement.cpp b/src/layerelement.cpp index d7bd8b4cd16..3a0f99bb6e2 100644 --- a/src/layerelement.cpp +++ b/src/layerelement.cpp @@ -73,7 +73,7 @@ namespace vrv { // Large spacing between syllables is a quarter note space -// MAX_DURATION / pow(2.0, (DUR_4 - 2.0)) +// MAX_DURATION / pow(2.0, (DURATION_4 - 2.0)) #define NEUME_LARGE_SPACE 256 // Medium spacing between neume is a 8th note space // MAX_DURATION / pow(2.0, (DUR_5 - 2.0)) @@ -554,7 +554,7 @@ int LayerElement::GetDrawingTop(const Doc *doc, int staffSize, bool withArtic, A if (note) { const DurationInterface *durationInterface = this->GetDurationInterface(); assert(durationInterface); - if (durationInterface->GetNoteOrChordDur(this) < DUR_2) { + if (durationInterface->GetNoteOrChordDur(this) < DURATION_2) { return note->GetDrawingY() + doc->GetDrawingUnit(staffSize); } // We should also take into account the stem shift to the right @@ -592,7 +592,7 @@ int LayerElement::GetDrawingBottom(const Doc *doc, int staffSize, bool withArtic if (note) { const DurationInterface *durationInterface = this->GetDurationInterface(); assert(durationInterface); - if (durationInterface->GetNoteOrChordDur(this) < DUR_2) { + if (durationInterface->GetNoteOrChordDur(this) < DURATION_2) { return note->GetDrawingY() - doc->GetDrawingUnit(staffSize); } // We should also take into account the stem shift to the right @@ -616,7 +616,7 @@ int LayerElement::GetDrawingRadius(const Doc *doc, bool isInLigature) const if (!this->Is({ CHORD, NC, NOTE, REST })) return 0; char32_t code = 0; - int dur = DUR_4; + int dur = DURATION_4; const Staff *staff = this->GetAncestorStaff(); bool isMensuralDur = false; if (this->Is(NOTE)) { @@ -636,13 +636,13 @@ int LayerElement::GetDrawingRadius(const Doc *doc, bool isInLigature) const assert(chord); dur = chord->GetActualDur(); isMensuralDur = chord->IsMensuralDur(); - if (dur == DUR_BR) { + if (dur == DURATION_breve) { code = SMUFL_E0A1_noteheadDoubleWholeSquare; } - else if (dur == DUR_1) { + else if (dur == DURATION_1) { code = SMUFL_E0A2_noteheadWhole; } - else if (dur == DUR_2) { + else if (dur == DURATION_2) { code = SMUFL_E0A3_noteheadHalf; } else { @@ -653,9 +653,9 @@ int LayerElement::GetDrawingRadius(const Doc *doc, bool isInLigature) const code = SMUFL_E0A4_noteheadBlack; } - // Mensural note shorter than DUR_BR - if ((isMensuralDur && (dur <= DUR_BR)) || ((dur == DUR_1) && isInLigature)) { - int widthFactor = (dur == DUR_MX) ? 2 : 1; + // Mensural note shorter than DURATION_breve + if ((isMensuralDur && (dur <= DURATION_breve)) || ((dur == DURATION_1) && isInLigature)) { + int widthFactor = (dur == DURATION_maxima) ? 2 : 1; if (staff->m_drawingNotationType == NOTATIONTYPE_mensural_black) { return widthFactor * doc->GetDrawingBrevisWidth(staff->m_drawingStaffSize) * 0.7; } @@ -1212,11 +1212,11 @@ std::pair LayerElement::CalcElementHorizontalOverlap(const Doc *doc, || ((STEMDIRECTION_up == stemDir) && (parentChord->GetTopNote() == previousNote)); } // Reduce the margin to 0 for whole notes unisson - else if ((currentNote->GetDrawingDur() == DUR_1) && (previousDuration == DUR_1)) { + else if ((currentNote->GetDrawingDur() == DURATION_1) && (previousDuration == DURATION_1)) { horizontalMargin = 0; } if (!isPreviousChord || isEdgeElement || isChordElement) { - if ((currentNote->GetDrawingDur() == DUR_2) && (previousDuration == DUR_2)) { + if ((currentNote->GetDrawingDur() == DURATION_2) && (previousDuration == DURATION_2)) { isInUnison = true; } else if ((!currentNote->IsGraceNote() && !currentNote->GetDrawingCueSize()) @@ -1232,7 +1232,7 @@ std::pair LayerElement::CalcElementHorizontalOverlap(const Doc *doc, isInUnison = true; continue; } - else if ((currentNote->GetDrawingDur() > DUR_2) && (previousDuration > DUR_2)) { + else if ((currentNote->GetDrawingDur() > DURATION_2) && (previousDuration > DURATION_2)) { isInUnison = true; } if (isInUnison && (currentNote->GetDots() == previousNote->GetDots())) { @@ -1240,7 +1240,8 @@ std::pair LayerElement::CalcElementHorizontalOverlap(const Doc *doc, } else { isInUnison = false; - if ((currentNote->GetDrawingDur() <= DUR_1) || (previousNote->GetDrawingDur() <= DUR_1)) { + if ((currentNote->GetDrawingDur() <= DURATION_1) + || (previousNote->GetDrawingDur() <= DURATION_1)) { horizontalMargin *= -1; } else { @@ -1263,7 +1264,8 @@ std::pair LayerElement::CalcElementHorizontalOverlap(const Doc *doc, if (previousNote->GetDrawingLoc() - currentNote->GetDrawingLoc() == -1) { horizontalMargin *= -1; } - else if ((currentNote->GetDrawingDur() <= DUR_1) && (previousNote->GetDrawingDur() <= DUR_1)) { + else if ((currentNote->GetDrawingDur() <= DURATION_1) + && (previousNote->GetDrawingDur() <= DURATION_1)) { continue; } else if (previousNote->m_crossStaff || m_crossStaff) diff --git a/src/note.cpp b/src/note.cpp index 08b8ad11ca2..1037dd17315 100644 --- a/src/note.cpp +++ b/src/note.cpp @@ -473,7 +473,7 @@ int Note::CalcStemLenInThirdUnits(const Staff *staff, data_STEMDIRECTION stemDir // Limit shortening with duration shorter than quarter not when not in a beam - if ((this->GetDrawingDur() > DUR_4) && !this->IsInBeam()) { + if ((this->GetDrawingDur() > DURATION_4) && !this->IsInBeam()) { if (this->GetDrawingStemDir() == STEMDIRECTION_up) { shortening = std::min(4, shortening); } @@ -494,7 +494,7 @@ char32_t Note::GetMensuralNoteheadGlyph() const int drawingDur = this->GetDrawingDur(); // No SMuFL code used for these values - if (drawingDur < DUR_1) { + if (drawingDur < DURATION_1) { return 0; } @@ -507,7 +507,7 @@ char32_t Note::GetMensuralNoteheadGlyph() const } else { if (this->GetColored() == BOOLEAN_true) { - if (drawingDur > DUR_2) { + if (drawingDur > DURATION_2) { code = SMUFL_E93C_mensuralNoteheadMinimaWhite; } else { @@ -515,7 +515,7 @@ char32_t Note::GetMensuralNoteheadGlyph() const } } else { - if (drawingDur > DUR_2) { + if (drawingDur > DURATION_2) { code = SMUFL_E93D_mensuralNoteheadSemiminimaWhite; } else { @@ -549,7 +549,7 @@ char32_t Note::GetNoteheadGlyph(const int duration) const // case HEADSHAPE_circle: return SMUFL_E0B3_noteheadCircleX; case HEADSHAPE_plus: return SMUFL_E0AF_noteheadPlusBlack; case HEADSHAPE_diamond: { - if (duration < DUR_4) { + if (duration < DURATION_4) { return (this->GetHeadFill() == FILL_solid) ? SMUFL_E0DB_noteheadDiamondBlack : SMUFL_E0D9_noteheadDiamondHalf; } @@ -562,7 +562,7 @@ char32_t Note::GetNoteheadGlyph(const int duration) const // case HEADSHAPE_oval: return SMUFL_noteheadOval; // case HEADSHAPE_piewedge: return SMUFL_noteheadPieWedge; case HEADSHAPE_rectangle: - if (duration < DUR_4) { + if (duration < DURATION_4) { return (this->GetHeadFill() == FILL_solid) ? SMUFL_E0B9_noteheadSquareBlack : SMUFL_E0B8_noteheadSquareWhite; } @@ -573,14 +573,14 @@ char32_t Note::GetNoteheadGlyph(const int duration) const // case HEADSHAPE_rtriangle: return SMUFL_noteheadRTriangle; // case HEADSHAPE_semicircle: return SMUFL_noteheadSemicircle; case HEADSHAPE_slash: { - if (DUR_1 >= duration) return SMUFL_E102_noteheadSlashWhiteWhole; - if (DUR_2 == duration) return SMUFL_E103_noteheadSlashWhiteHalf; + if (DURATION_1 >= duration) return SMUFL_E102_noteheadSlashWhiteWhole; + if (DURATION_2 == duration) return SMUFL_E103_noteheadSlashWhiteHalf; return SMUFL_E101_noteheadSlashHorizontalEnds; } // case HEADSHAPE_square: return SMUFL_noteheadSquare; case HEADSHAPE_x: { - if (DUR_1 == duration) return SMUFL_E0B5_noteheadWholeWithX; - if (DUR_2 == duration) return SMUFL_E0B6_noteheadHalfWithX; + if (DURATION_1 == duration) return SMUFL_E0B5_noteheadWholeWithX; + if (DURATION_2 == duration) return SMUFL_E0B6_noteheadHalfWithX; return SMUFL_E0A9_noteheadXBlack; } default: break; @@ -591,10 +591,10 @@ char32_t Note::GetNoteheadGlyph(const int duration) const default: break; } - if (DUR_BR == duration) return SMUFL_E0A1_noteheadDoubleWholeSquare; - if (DUR_1 == duration) return SMUFL_E0A2_noteheadWhole; + if (DURATION_breve == duration) return SMUFL_E0A1_noteheadDoubleWholeSquare; + if (DURATION_1 == duration) return SMUFL_E0A2_noteheadWhole; // We support solid on half notes or void on quarter and shorter notes - if (DUR_2 == duration) { + if (DURATION_2 == duration) { return (this->GetHeadFill() == FILL_solid) ? SMUFL_E0A4_noteheadBlack : SMUFL_E0A3_noteheadHalf; } else { diff --git a/src/page.cpp b/src/page.cpp index 17388407eb8..cab9e92fea6 100644 --- a/src/page.cpp +++ b/src/page.cpp @@ -318,7 +318,7 @@ void Page::ResetAligners() // Unless duration-based spacing is disabled, set the X position of each Alignment. // Does non-linear spacing based on the duration space between two Alignment objects. if (!doc->GetOptions()->m_evenNoteSpacing.GetValue()) { - int longestActualDur = DUR_4; + int longestActualDur = DURATION_4; // Detect the longest duration in order to adjust the spacing (false by default) if (doc->GetOptions()->m_spacingDurDetection.GetValue()) { diff --git a/src/preparedatafunctor.cpp b/src/preparedatafunctor.cpp index 1bb1389a6a6..091b6be6d54 100644 --- a/src/preparedatafunctor.cpp +++ b/src/preparedatafunctor.cpp @@ -1102,11 +1102,11 @@ FunctorCode PrepareLayerElementPartsFunctor::VisitChord(Chord *chord) currentStem->FillAttributes(*chord); int duration = chord->GetNoteOrChordDur(chord); - if ((duration < DUR_2) || (chord->GetStemVisible() == BOOLEAN_false)) { + if ((duration < DURATION_2) || (chord->GetStemVisible() == BOOLEAN_false)) { currentStem->IsVirtual(true); } - const bool shouldHaveFlag = ((duration > DUR_4) && !chord->IsInBeam() && !chord->GetAncestorFTrem()); + const bool shouldHaveFlag = ((duration > DURATION_4) && !chord->IsInBeam() && !chord->GetAncestorFTrem()); currentFlag = this->ProcessFlag(currentFlag, currentStem, shouldHaveFlag); chord->SetDrawingStem(currentStem); @@ -1150,7 +1150,7 @@ FunctorCode PrepareLayerElementPartsFunctor::VisitNote(Note *note) currentStem->AttGraced::operator=(*note); currentStem->FillAttributes(*note); - if (note->GetActualDur() < DUR_2 || (note->GetStemVisible() == BOOLEAN_false)) { + if (note->GetActualDur() < DURATION_2 || (note->GetStemVisible() == BOOLEAN_false)) { currentStem->IsVirtual(true); } } @@ -1177,8 +1177,8 @@ FunctorCode PrepareLayerElementPartsFunctor::VisitNote(Note *note) if (note->IsMensuralDur()) return FUNCTOR_CONTINUE; if (currentStem) { - const bool shouldHaveFlag = ((note->GetActualDur() > DUR_4) && !note->IsInBeam() && !note->GetAncestorFTrem() - && !note->IsChordTone() && !note->IsTabGrpNote()); + const bool shouldHaveFlag = ((note->GetActualDur() > DURATION_4) && !note->IsInBeam() + && !note->GetAncestorFTrem() && !note->IsChordTone() && !note->IsTabGrpNote()); currentFlag = this->ProcessFlag(currentFlag, currentStem, shouldHaveFlag); if (!chord) note->SetDrawingStem(currentStem); @@ -1196,7 +1196,7 @@ FunctorCode PrepareLayerElementPartsFunctor::VisitRest(Rest *rest) { Dots *currentDots = vrv_cast(rest->FindDescendantByType(DOTS, 1)); - const bool shouldHaveDots = (rest->GetDur() > DUR_BR) && (rest->GetDots() > 0); + const bool shouldHaveDots = (rest->GetDur() > DURATION_breve) && (rest->GetDots() > 0); currentDots = this->ProcessDots(currentDots, rest, shouldHaveDots); /************ Prepare the drawing cue size ************/ @@ -1222,7 +1222,7 @@ FunctorCode PrepareLayerElementPartsFunctor::VisitTabDurSym(TabDurSym *tabDurSym assert(tabGrp); // No flag within beam for durations longer than 8th notes - const bool shouldHaveFlag = (!tabDurSym->IsInBeam() && (tabGrp->GetActualDur() > DUR_4)); + const bool shouldHaveFlag = (!tabDurSym->IsInBeam() && (tabGrp->GetActualDur() > DURATION_4)); currentFlag = this->ProcessFlag(currentFlag, currentStem, shouldHaveFlag); return FUNCTOR_SIBLINGS; diff --git a/src/rest.cpp b/src/rest.cpp index 5f0779dd004..444159f8e63 100644 --- a/src/rest.cpp +++ b/src/rest.cpp @@ -37,100 +37,118 @@ RestOffsets g_defaultRests{ { { RA_none, { { RLP_restOnTopLayer, { { RNP_noteInSpace, - { { DUR_1, 3 }, { DUR_2, 3 }, { DUR_4, 5 }, { DUR_8, 5 }, { DUR_16, 7 }, { DUR_32, 7 }, - { DUR_64, 9 }, { DUR_128, 9 }, { DUR_LG, 5 }, { DUR_BR, 5 } } }, + { { DURATION_1, 3 }, { DURATION_2, 3 }, { DURATION_4, 5 }, { DURATION_8, 5 }, + { DURATION_16, 7 }, { DURATION_32, 7 }, { DURATION_64, 9 }, { DURATION_128, 9 }, + { DURATION_long, 5 }, { DURATION_breve, 5 } } }, { RNP_noteOnLine, - { { DUR_1, 2 }, { DUR_2, 4 }, { DUR_4, 6 }, { DUR_8, 4 }, { DUR_16, 6 }, { DUR_32, 6 }, - { DUR_64, 8 }, { DUR_128, 8 }, { DUR_LG, 6 }, { DUR_BR, 4 } } } } }, + { { DURATION_1, 2 }, { DURATION_2, 4 }, { DURATION_4, 6 }, { DURATION_8, 4 }, + { DURATION_16, 6 }, { DURATION_32, 6 }, { DURATION_64, 8 }, { DURATION_128, 8 }, + { DURATION_long, 6 }, { DURATION_breve, 4 } } } } }, { RLP_restOnBottomLayer, { { RNP_noteInSpace, - { { DUR_1, -5 }, { DUR_2, -5 }, { DUR_4, -5 }, { DUR_8, -5 }, { DUR_16, -5 }, - { DUR_32, -7 }, { DUR_64, -7 }, { DUR_128, -9 }, { DUR_LG, -5 }, { DUR_BR, -5 } } }, + { { DURATION_1, -5 }, { DURATION_2, -5 }, { DURATION_4, -5 }, { DURATION_8, -5 }, + { DURATION_16, -5 }, { DURATION_32, -7 }, { DURATION_64, -7 }, { DURATION_128, -9 }, + { DURATION_long, -5 }, { DURATION_breve, -5 } } }, { RNP_noteOnLine, - { { DUR_1, -6 }, { DUR_2, -6 }, { DUR_4, -6 }, { DUR_8, -4 }, { DUR_16, -4 }, - { DUR_32, -6 }, { DUR_64, -6 }, { DUR_128, -8 }, { DUR_LG, -6 }, - { DUR_BR, -6 } } } } } } }, + { { DURATION_1, -6 }, { DURATION_2, -6 }, { DURATION_4, -6 }, { DURATION_8, -4 }, + { DURATION_16, -4 }, { DURATION_32, -6 }, { DURATION_64, -6 }, { DURATION_128, -8 }, + { DURATION_long, -6 }, { DURATION_breve, -6 } } } } } } }, { RA_s, { { RLP_restOnTopLayer, { { RNP_noteInSpace, - { { DUR_1, 3 }, { DUR_2, 5 }, { DUR_4, 7 }, { DUR_8, 5 }, { DUR_16, 7 }, { DUR_32, 7 }, - { DUR_64, 9 }, { DUR_128, 9 }, { DUR_LG, 5 }, { DUR_BR, 5 } } }, + { { DURATION_1, 3 }, { DURATION_2, 5 }, { DURATION_4, 7 }, { DURATION_8, 5 }, + { DURATION_16, 7 }, { DURATION_32, 7 }, { DURATION_64, 9 }, { DURATION_128, 9 }, + { DURATION_long, 5 }, { DURATION_breve, 5 } } }, { RNP_noteOnLine, - { { DUR_1, 2 }, { DUR_2, 4 }, { DUR_4, 6 }, { DUR_8, 6 }, { DUR_16, 8 }, { DUR_32, 8 }, - { DUR_64, 10 }, { DUR_128, 10 }, { DUR_LG, 6 }, { DUR_BR, 4 } } } } }, + { { DURATION_1, 2 }, { DURATION_2, 4 }, { DURATION_4, 6 }, { DURATION_8, 6 }, + { DURATION_16, 8 }, { DURATION_32, 8 }, { DURATION_64, 10 }, { DURATION_128, 10 }, + { DURATION_long, 6 }, { DURATION_breve, 4 } } } } }, { RLP_restOnBottomLayer, { { RNP_noteInSpace, - { { DUR_1, -5 }, { DUR_2, -5 }, { DUR_4, -5 }, { DUR_8, -5 }, { DUR_16, -5 }, - { DUR_32, -7 }, { DUR_64, -7 }, { DUR_128, -9 }, { DUR_LG, -5 }, { DUR_BR, -5 } } }, + { { DURATION_1, -5 }, { DURATION_2, -5 }, { DURATION_4, -5 }, { DURATION_8, -5 }, + { DURATION_16, -5 }, { DURATION_32, -7 }, { DURATION_64, -7 }, { DURATION_128, -9 }, + { DURATION_long, -5 }, { DURATION_breve, -5 } } }, { RNP_noteOnLine, - { { DUR_1, -6 }, { DUR_2, -6 }, { DUR_4, -6 }, { DUR_8, -6 }, { DUR_16, -6 }, - { DUR_32, -6 }, { DUR_64, -6 }, { DUR_128, -8 }, { DUR_LG, -6 }, - { DUR_BR, -6 } } } } } } }, + { { DURATION_1, -6 }, { DURATION_2, -6 }, { DURATION_4, -6 }, { DURATION_8, -6 }, + { DURATION_16, -6 }, { DURATION_32, -6 }, { DURATION_64, -6 }, { DURATION_128, -8 }, + { DURATION_long, -6 }, { DURATION_breve, -6 } } } } } } }, { RA_f, { { RLP_restOnTopLayer, { { RNP_noteInSpace, - { { DUR_1, 3 }, { DUR_2, 5 }, { DUR_4, 5 }, { DUR_8, 5 }, { DUR_16, 7 }, { DUR_32, 7 }, - { DUR_64, 9 }, { DUR_128, 9 }, { DUR_LG, 5 }, { DUR_BR, 5 } } }, + { { DURATION_1, 3 }, { DURATION_2, 5 }, { DURATION_4, 5 }, { DURATION_8, 5 }, + { DURATION_16, 7 }, { DURATION_32, 7 }, { DURATION_64, 9 }, { DURATION_128, 9 }, + { DURATION_long, 5 }, { DURATION_breve, 5 } } }, { RNP_noteOnLine, - { { DUR_1, 4 }, { DUR_2, 4 }, { DUR_4, 6 }, { DUR_8, 6 }, { DUR_16, 8 }, { DUR_32, 8 }, - { DUR_64, 10 }, { DUR_128, 10 }, { DUR_LG, 6 }, { DUR_BR, 4 } } } } }, + { { DURATION_1, 4 }, { DURATION_2, 4 }, { DURATION_4, 6 }, { DURATION_8, 6 }, + { DURATION_16, 8 }, { DURATION_32, 8 }, { DURATION_64, 10 }, { DURATION_128, 10 }, + { DURATION_long, 6 }, { DURATION_breve, 4 } } } } }, { RLP_restOnBottomLayer, { { RNP_noteInSpace, - { { DUR_1, -5 }, { DUR_2, -5 }, { DUR_4, -5 }, { DUR_8, -5 }, { DUR_16, -5 }, - { DUR_32, -7 }, { DUR_64, -7 }, { DUR_128, -9 }, { DUR_LG, -5 }, { DUR_BR, -5 } } }, + { { DURATION_1, -5 }, { DURATION_2, -5 }, { DURATION_4, -5 }, { DURATION_8, -5 }, + { DURATION_16, -5 }, { DURATION_32, -7 }, { DURATION_64, -7 }, { DURATION_128, -9 }, + { DURATION_long, -5 }, { DURATION_breve, -5 } } }, { RNP_noteOnLine, - { { DUR_1, -6 }, { DUR_2, -6 }, { DUR_4, -6 }, { DUR_8, -4 }, { DUR_16, -4 }, - { DUR_32, -6 }, { DUR_64, -6 }, { DUR_128, -8 }, { DUR_LG, -6 }, - { DUR_BR, -6 } } } } } } }, + { { DURATION_1, -6 }, { DURATION_2, -6 }, { DURATION_4, -6 }, { DURATION_8, -4 }, + { DURATION_16, -4 }, { DURATION_32, -6 }, { DURATION_64, -6 }, { DURATION_128, -8 }, + { DURATION_long, -6 }, { DURATION_breve, -6 } } } } } } }, { RA_x, { { RLP_restOnTopLayer, { { RNP_noteInSpace, - { { DUR_1, 3 }, { DUR_2, 3 }, { DUR_4, 5 }, { DUR_8, 5 }, { DUR_16, 7 }, { DUR_32, 7 }, - { DUR_64, 9 }, { DUR_128, 9 }, { DUR_LG, 5 }, { DUR_BR, 5 } } }, + { { DURATION_1, 3 }, { DURATION_2, 3 }, { DURATION_4, 5 }, { DURATION_8, 5 }, + { DURATION_16, 7 }, { DURATION_32, 7 }, { DURATION_64, 9 }, { DURATION_128, 9 }, + { DURATION_long, 5 }, { DURATION_breve, 5 } } }, { RNP_noteOnLine, - { { DUR_1, 2 }, { DUR_2, 4 }, { DUR_4, 6 }, { DUR_8, 6 }, { DUR_16, 8 }, { DUR_32, 8 }, - { DUR_64, 10 }, { DUR_128, 10 }, { DUR_LG, 6 }, { DUR_BR, 4 } } } } }, + { { DURATION_1, 2 }, { DURATION_2, 4 }, { DURATION_4, 6 }, { DURATION_8, 6 }, + { DURATION_16, 8 }, { DURATION_32, 8 }, { DURATION_64, 10 }, { DURATION_128, 10 }, + { DURATION_long, 6 }, { DURATION_breve, 4 } } } } }, { RLP_restOnBottomLayer, { { RNP_noteInSpace, - { { DUR_1, -5 }, { DUR_2, -5 }, { DUR_4, -5 }, { DUR_8, -5 }, { DUR_16, -5 }, - { DUR_32, -7 }, { DUR_64, -7 }, { DUR_128, -9 }, { DUR_LG, -5 }, { DUR_BR, -5 } } }, + { { DURATION_1, -5 }, { DURATION_2, -5 }, { DURATION_4, -5 }, { DURATION_8, -5 }, + { DURATION_16, -5 }, { DURATION_32, -7 }, { DURATION_64, -7 }, { DURATION_128, -9 }, + { DURATION_long, -5 }, { DURATION_breve, -5 } } }, { RNP_noteOnLine, - { { DUR_1, -6 }, { DUR_2, -4 }, { DUR_4, -6 }, { DUR_8, -4 }, { DUR_16, -4 }, - { DUR_32, -6 }, { DUR_64, -6 }, { DUR_128, -8 }, { DUR_LG, -6 }, - { DUR_BR, -6 } } } } } } }, + { { DURATION_1, -6 }, { DURATION_2, -4 }, { DURATION_4, -6 }, { DURATION_8, -4 }, + { DURATION_16, -4 }, { DURATION_32, -6 }, { DURATION_64, -6 }, { DURATION_128, -8 }, + { DURATION_long, -6 }, { DURATION_breve, -6 } } } } } } }, { RA_n, { { RLP_restOnTopLayer, { { RNP_noteInSpace, - { { DUR_1, 3 }, { DUR_2, 3 }, { DUR_4, 5 }, { DUR_8, 5 }, { DUR_16, 7 }, { DUR_32, 7 }, - { DUR_64, 9 }, { DUR_128, 9 }, { DUR_LG, 5 }, { DUR_BR, 5 } } }, + { { DURATION_1, 3 }, { DURATION_2, 3 }, { DURATION_4, 5 }, { DURATION_8, 5 }, + { DURATION_16, 7 }, { DURATION_32, 7 }, { DURATION_64, 9 }, { DURATION_128, 9 }, + { DURATION_long, 5 }, { DURATION_breve, 5 } } }, { RNP_noteOnLine, - { { DUR_1, 2 }, { DUR_2, 6 }, { DUR_4, 6 }, { DUR_8, 6 }, { DUR_16, 8 }, { DUR_32, 8 }, - { DUR_64, 10 }, { DUR_128, 10 }, { DUR_LG, 6 }, { DUR_BR, 4 } } } } }, + { { DURATION_1, 2 }, { DURATION_2, 6 }, { DURATION_4, 6 }, { DURATION_8, 6 }, + { DURATION_16, 8 }, { DURATION_32, 8 }, { DURATION_64, 10 }, { DURATION_128, 10 }, + { DURATION_long, 6 }, { DURATION_breve, 4 } } } } }, { RLP_restOnBottomLayer, { { RNP_noteInSpace, - { { DUR_1, -7 }, { DUR_2, -5 }, { DUR_4, -7 }, { DUR_8, -5 }, { DUR_16, -5 }, - { DUR_32, -7 }, { DUR_64, -7 }, { DUR_128, -9 }, { DUR_LG, -5 }, { DUR_BR, -5 } } }, + { { DURATION_1, -7 }, { DURATION_2, -5 }, { DURATION_4, -7 }, { DURATION_8, -5 }, + { DURATION_16, -5 }, { DURATION_32, -7 }, { DURATION_64, -7 }, { DURATION_128, -9 }, + { DURATION_long, -5 }, { DURATION_breve, -5 } } }, { RNP_noteOnLine, - { { DUR_1, -6 }, { DUR_2, -6 }, { DUR_4, -6 }, { DUR_8, -6 }, { DUR_16, -6 }, - { DUR_32, -6 }, { DUR_64, -6 }, { DUR_128, -8 }, { DUR_LG, -6 }, - { DUR_BR, -6 } } } } } } } } }, + { { DURATION_1, -6 }, { DURATION_2, -6 }, { DURATION_4, -6 }, { DURATION_8, -6 }, + { DURATION_16, -6 }, { DURATION_32, -6 }, { DURATION_64, -6 }, { DURATION_128, -8 }, + { DURATION_long, -6 }, { DURATION_breve, -6 } } } } } } } } }, { RL_sameLayer, { { RA_none, { { RLP_restOnTopLayer, { { RNP_noteInSpace, - { { DUR_1, -1 }, { DUR_2, 1 }, { DUR_4, 1 }, { DUR_8, 1 }, { DUR_16, 3 }, { DUR_32, 3 }, - { DUR_64, 5 }, { DUR_128, 5 }, { DUR_LG, 3 }, { DUR_BR, 1 } } }, + { { DURATION_1, -1 }, { DURATION_2, 1 }, { DURATION_4, 1 }, { DURATION_8, 1 }, + { DURATION_16, 3 }, { DURATION_32, 3 }, { DURATION_64, 5 }, { DURATION_128, 5 }, + { DURATION_long, 3 }, { DURATION_breve, 1 } } }, { RNP_noteOnLine, - { { DUR_1, 0 }, { DUR_2, 0 }, { DUR_4, 2 }, { DUR_8, 2 }, { DUR_16, 2 }, { DUR_32, 2 }, - { DUR_64, 4 }, { DUR_128, 4 }, { DUR_LG, 2 }, { DUR_BR, 2 } } } } }, + { { DURATION_1, 0 }, { DURATION_2, 0 }, { DURATION_4, 2 }, { DURATION_8, 2 }, + { DURATION_16, 2 }, { DURATION_32, 2 }, { DURATION_64, 4 }, { DURATION_128, 4 }, + { DURATION_long, 2 }, { DURATION_breve, 2 } } } } }, { RLP_restOnBottomLayer, { { RNP_noteInSpace, - { { DUR_1, -3 }, { DUR_2, -1 }, { DUR_4, -1 }, { DUR_8, -1 }, { DUR_16, -1 }, { DUR_32, -3 }, - { DUR_64, -3 }, { DUR_128, -5 }, { DUR_LG, -3 }, { DUR_BR, -3 } } }, + { { DURATION_1, -3 }, { DURATION_2, -1 }, { DURATION_4, -1 }, { DURATION_8, -1 }, + { DURATION_16, -1 }, { DURATION_32, -3 }, { DURATION_64, -3 }, { DURATION_128, -5 }, + { DURATION_long, -3 }, { DURATION_breve, -3 } } }, { RNP_noteOnLine, - { { DUR_1, -2 }, { DUR_2, -2 }, { DUR_4, -2 }, { DUR_8, -2 }, { DUR_16, -2 }, - { DUR_32, -4 }, { DUR_64, -4 }, { DUR_128, -6 }, { DUR_LG, -2 }, - { DUR_BR, -2 } } } } } } } } } + { { DURATION_1, -2 }, { DURATION_2, -2 }, { DURATION_4, -2 }, { DURATION_8, -2 }, + { DURATION_16, -2 }, { DURATION_32, -4 }, { DURATION_64, -4 }, { DURATION_128, -6 }, + { DURATION_long, -2 }, { DURATION_breve, -2 } } } } } } } } } }; // helper function for conversion @@ -244,31 +262,31 @@ char32_t Rest::GetRestGlyph(const int duration) const if (this->IsMensuralDur()) { switch (duration) { - case DUR_MX: return SMUFL_E9F0_mensuralRestMaxima; break; - case DUR_LG: return SMUFL_E9F2_mensuralRestLongaImperfecta; break; - case DUR_BR: return SMUFL_E9F3_mensuralRestBrevis; break; - case DUR_1: return SMUFL_E9F4_mensuralRestSemibrevis; break; - case DUR_2: return SMUFL_E9F5_mensuralRestMinima; break; - case DUR_4: return SMUFL_E9F6_mensuralRestSemiminima; break; - case DUR_8: return SMUFL_E9F7_mensuralRestFusa; break; - case DUR_16: return SMUFL_E9F8_mensuralRestSemifusa; break; + case DURATION_maxima: return SMUFL_E9F0_mensuralRestMaxima; break; + case DURATION_long: return SMUFL_E9F2_mensuralRestLongaImperfecta; break; + case DURATION_breve: return SMUFL_E9F3_mensuralRestBrevis; break; + case DURATION_1: return SMUFL_E9F4_mensuralRestSemibrevis; break; + case DURATION_2: return SMUFL_E9F5_mensuralRestMinima; break; + case DURATION_4: return SMUFL_E9F6_mensuralRestSemiminima; break; + case DURATION_8: return SMUFL_E9F7_mensuralRestFusa; break; + case DURATION_16: return SMUFL_E9F8_mensuralRestSemifusa; break; } } else { switch (duration) { - case DUR_LG: return SMUFL_E4E1_restLonga; break; - case DUR_BR: return SMUFL_E4E2_restDoubleWhole; break; - case DUR_1: return SMUFL_E4E3_restWhole; break; - case DUR_2: return SMUFL_E4E4_restHalf; break; - case DUR_4: return SMUFL_E4E5_restQuarter; break; - case DUR_8: return SMUFL_E4E6_rest8th; break; - case DUR_16: return SMUFL_E4E7_rest16th; break; - case DUR_32: return SMUFL_E4E8_rest32nd; break; - case DUR_64: return SMUFL_E4E9_rest64th; break; - case DUR_128: return SMUFL_E4EA_rest128th; break; - case DUR_256: return SMUFL_E4EB_rest256th; break; - case DUR_512: return SMUFL_E4EC_rest512th; break; - case DUR_1024: return SMUFL_E4ED_rest1024th; break; + case DURATION_long: return SMUFL_E4E1_restLonga; break; + case DURATION_breve: return SMUFL_E4E2_restDoubleWhole; break; + case DURATION_1: return SMUFL_E4E3_restWhole; break; + case DURATION_2: return SMUFL_E4E4_restHalf; break; + case DURATION_4: return SMUFL_E4E5_restQuarter; break; + case DURATION_8: return SMUFL_E4E6_rest8th; break; + case DURATION_16: return SMUFL_E4E7_rest16th; break; + case DURATION_32: return SMUFL_E4E8_rest32nd; break; + case DURATION_64: return SMUFL_E4E9_rest64th; break; + case DURATION_128: return SMUFL_E4EA_rest128th; break; + case DURATION_256: return SMUFL_E4EB_rest256th; break; + case DURATION_512: return SMUFL_E4EC_rest512th; break; + case DURATION_1024: return SMUFL_E4ED_rest1024th; break; } } @@ -543,8 +561,8 @@ int Rest::GetRestOffsetFromOptions( { int duration = this->GetActualDur(); // Make sure we are in the boundaries of g_defaultRests - if (duration > DUR_128) duration = DUR_128; - if (duration < DUR_LG) duration = DUR_LG; + if (duration > DURATION_128) duration = DURATION_128; + if (duration < DURATION_long) duration = DURATION_long; return g_defaultRests.at(layer) .at(RL_sameLayer == layer ? location.second : RA_none) .at(isTopLayer ? RLP_restOnTopLayer : RLP_restOnBottomLayer) diff --git a/src/view_beam.cpp b/src/view_beam.cpp index 34d04de9f06..566234d1cc3 100644 --- a/src/view_beam.cpp +++ b/src/view_beam.cpp @@ -152,7 +152,7 @@ void View::DrawFTremSegment(DeviceContext *dc, Staff *staff, FTrem *fTrem) if (!durationElement) return; const int dur = durationElement->GetDur(); - if (dur > DUR_1) { + if (dur > DURATION_1) { // Adjust the x position of the first and last element for taking into account the stem width firstElement->m_x -= (m_doc->GetDrawingStemWidth(staff->m_drawingStaffSize)) / 2; secondElement->m_x += (m_doc->GetDrawingStemWidth(staff->m_drawingStaffSize)) / 2; @@ -177,7 +177,7 @@ void View::DrawFTremSegment(DeviceContext *dc, Staff *staff, FTrem *fTrem) int space = m_doc->GetDrawingBeamWidth(staff->m_drawingStaffSize, fTrem->m_cueSize); // for non-stem notes the bar should be shortened - if (dur < DUR_2) { + if (dur < DURATION_2) { if (fTrem->m_drawingPlace == BEAMPLACE_below) x1 += 2 * space; y1 += 2 * space * fTrem->m_beamSegment.m_beamSlope; if (fTrem->m_drawingPlace == BEAMPLACE_above) x2 -= 2 * space; @@ -186,7 +186,7 @@ void View::DrawFTremSegment(DeviceContext *dc, Staff *staff, FTrem *fTrem) fullBars = allBars; floatingBars = 0; } - else if ((dur > DUR_2) && !floatingBars) { + else if ((dur > DURATION_2) && !floatingBars) { fullBars = dur - 4; floatingBars = allBars - fullBars; } @@ -289,12 +289,12 @@ void View::DrawBeamSegment( } int noteCount = (int)noteIndexes.size(); - int durRef = DUR_8; - int durRef2 = DUR_16; + int durRef = DURATION_8; + int durRef2 = DURATION_16; if (staff->IsTabLuteFrench() || staff->IsTabLuteItalian()) { - durRef = DUR_4; - durRef2 = DUR_8; + durRef = DURATION_4; + durRef2 = DURATION_8; } int barY = 0; diff --git a/src/view_element.cpp b/src/view_element.cpp index ee980ff0d13..0f15863eab9 100644 --- a/src/view_element.cpp +++ b/src/view_element.cpp @@ -285,7 +285,7 @@ void View::DrawAccid(DeviceContext *dc, LayerElement *element, Layer *layer, Sta if (accid->GetFunc() != accidLog_FUNC_edit) onStaff = (accid->GetOnstaff() != BOOLEAN_false); const int verticalCenter = staffTop - (staff->m_drawingLines - 1) * unit; const data_STEMDIRECTION stemDir = this->GetMensuralStemDir(layer, note, verticalCenter); - if ((drawingDur > DUR_1) || (drawingDur < DUR_BR)) { + if ((drawingDur > DURATION_1) || (drawingDur < DURATION_breve)) { if (stemDir == STEMDIRECTION_up) { noteTop = note->GetDrawingY() + unit * STANDARD_STEMLENGTH; noteBottom -= unit; @@ -600,7 +600,7 @@ void View::DrawChordCluster(DeviceContext *dc, Chord *chord, Layer *layer, Staff dc->StartCustomGraphic("notehead"); - if (chord->GetActualDur() < DUR_4) { + if (chord->GetActualDur() < DURATION_4) { const int line = unit / 2; this->DrawNotFilledRectangle(dc, x + line / 2, y1 - line / 2, x + width - line / 2, y2 + line / 2, line, 0); } @@ -1459,19 +1459,19 @@ void View::DrawNote(DeviceContext *dc, LayerElement *element, Layer *layer, Staf if (note->IsInBeam() && !dc->Is(BBOX_DEVICE_CONTEXT)) { LogWarning("Missing duration for note '%s' in beam", note->GetID().c_str()); } - drawingDur = DUR_4; + drawingDur = DURATION_4; } - if (drawingDur < DUR_BR) { + if (drawingDur < DURATION_breve) { this->DrawMaximaToBrevis(dc, noteY, element, layer, staff); } else { // Whole notes char32_t fontNo; if (note->GetColored() == BOOLEAN_true) { - if (DUR_1 == drawingDur) { + if (DURATION_1 == drawingDur) { fontNo = SMUFL_E0FA_noteheadWholeFilled; } - else if (DUR_2 == drawingDur) { + else if (DURATION_2 == drawingDur) { fontNo = SMUFL_E0FB_noteheadHalfFilled; } else { @@ -1544,7 +1544,7 @@ void View::DrawRest(DeviceContext *dc, LayerElement *element, Layer *layer, Staf if (!dc->Is(BBOX_DEVICE_CONTEXT)) { LogWarning("Missing duration for rest '%s'", rest->GetID().c_str()); } - drawingDur = DUR_4; + drawingDur = DURATION_4; } const char32_t drawingGlyph = rest->GetRestGlyph(drawingDur); @@ -1553,7 +1553,7 @@ void View::DrawRest(DeviceContext *dc, LayerElement *element, Layer *layer, Staf this->DrawSmuflCode(dc, x, y, drawingGlyph, staffSize, drawingCueSize); - if ((drawingDur == DUR_1 || drawingDur == DUR_2 || drawingDur == DUR_BR)) { + if ((drawingDur == DURATION_1 || drawingDur == DURATION_2 || drawingDur == DURATION_breve)) { const int width = m_doc->GetGlyphWidth(drawingGlyph, staffSize, drawingCueSize); int ledgerLineThickness = m_doc->GetOptions()->m_ledgerLineThickness.GetValue() * m_doc->GetDrawingUnit(staffSize); @@ -1569,14 +1569,14 @@ void View::DrawRest(DeviceContext *dc, LayerElement *element, Layer *layer, Staf dc->StartCustomGraphic("ledgerLines"); // single legder line for half and whole rests - if ((drawingDur == DUR_1 || drawingDur == DUR_2) && (y > topMargin || y < bottomMargin)) { + if ((drawingDur == DURATION_1 || drawingDur == DURATION_2) && (y > topMargin || y < bottomMargin)) { dc->DeactivateGraphicX(); this->DrawHorizontalLine( dc, x - ledgerLineExtension, x + width + ledgerLineExtension, y, ledgerLineThickness); dc->ReactivateGraphic(); } // double ledger line for breve rests - else if (drawingDur == DUR_BR && (y >= topMargin || y <= bottomMargin)) { + else if (drawingDur == DURATION_breve && (y >= topMargin || y <= bottomMargin)) { const int height = m_doc->GetGlyphHeight(drawingGlyph, staffSize, drawingCueSize); dc->DeactivateGraphicX(); if (y != topMargin) { @@ -1623,7 +1623,7 @@ void View::DrawStem(DeviceContext *dc, LayerElement *element, Layer *layer, Staf // We check if this belongs to a mensural note Note *parent = vrv_cast(stem->GetFirstAncestor(NOTE)); if (parent && parent->IsMensuralDur()) { - if (parent->GetDrawingDur() > DUR_1) { + if (parent->GetDrawingDur() > DURATION_1) { /************** Stem/notehead direction: **************/ const int staffCenter = staff->GetDrawingY() - m_doc->GetDrawingUnit(staff->m_drawingStaffSize) * (staff->m_drawingLines - 1); @@ -1717,7 +1717,8 @@ void View::DrawStemMod(DeviceContext *dc, LayerElement *element, Staff *staff) // calculate position for the stem mod const int y = note->GetDrawingY() + stemRelY; - const int x = (drawingDur <= DUR_1) ? childElement->GetDrawingX() + childElement->GetDrawingRadius(m_doc) : stemX; + const int x + = (drawingDur <= DURATION_1) ? childElement->GetDrawingX() + childElement->GetDrawingRadius(m_doc) : stemX; if ((code != SMUFL_E645_vocalSprechgesang) || !element->Is(BTREM)) { int adjust = 0; diff --git a/src/view_mensural.cpp b/src/view_mensural.cpp index 2423f321eaf..a02bc5f9cad 100644 --- a/src/view_mensural.cpp +++ b/src/view_mensural.cpp @@ -58,7 +58,7 @@ void View::DrawMensuralNote(DeviceContext *dc, LayerElement *element, Layer *lay if (note->IsInLigature() && !m_options->m_ligatureAsBracket.GetValue()) { this->DrawLigatureNote(dc, element, layer, staff); } - else if (drawingDur < DUR_1) { + else if (drawingDur < DURATION_1) { this->DrawMaximaToBrevis(dc, yNote, element, layer, staff); } // Semibrevis and shorter @@ -169,7 +169,7 @@ void View::DrawMensuralStem(DeviceContext *dc, Note *note, Staff *staff, data_ST /* In black notation, the semiminima gets one flag; in white notation, it gets none. In both cases, as in CWMN, each shorter duration gets one additional flag. */ - const int nbFlags = (mensural_black ? drawingDur - DUR_2 : drawingDur - DUR_4); + const int nbFlags = (mensural_black ? drawingDur - DURATION_2 : drawingDur - DURATION_4); // SMuFL's mensural stems are not centered const int halfStemWidth @@ -218,7 +218,7 @@ void View::DrawMaximaToBrevis(DeviceContext *dc, int y, LayerElement *element, L const int staffSize = staff->m_drawingStaffSize; int shape = LIGATURE_DEFAULT; - if (note->GetActualDur() != DUR_BR) { + if (note->GetActualDur() != DURATION_breve) { bool up = false; // Mensural notes have no Stem child - rely on the MEI @stem.dir if (note->GetStemDir() != STEMDIRECTION_NONE) { @@ -263,7 +263,7 @@ void View::DrawMaximaToBrevis(DeviceContext *dc, int y, LayerElement *element, L // serifs and / or stem this->DrawFilledRectangle(dc, topLeft.x, sides[0], topLeft.x + stemWidth, sides[1]); - if (note->GetActualDur() != DUR_BR) { + if (note->GetActualDur() != DURATION_breve) { // Right side is a stem - end the notehead first dc->EndCustomGraphic(); dc->StartCustomGraphic("stem"); @@ -449,7 +449,7 @@ void View::DrawDotInLigature(DeviceContext *dc, LayerElement *element, Layer *la isVerticalDot = !isLast && (shape & LIGATURE_OBLIQUE); } else { - if (note->GetActualDur() == DUR_1) shiftMultiplier = 3.5; + if (note->GetActualDur() == DURATION_1) shiftMultiplier = 3.5; } int y = note->GetDrawingY(); @@ -484,7 +484,7 @@ void View::DrawPlica(DeviceContext *dc, LayerElement *element, Layer *layer, Sta const bool isMensuralBlack = (staff->m_drawingNotationType == NOTATIONTYPE_mensural_black); const int stemWidth = m_doc->GetDrawingStemWidth(staff->m_drawingStaffSize); - const bool isLonga = (note->GetActualDur() == DUR_LG); + const bool isLonga = (note->GetActualDur() == DURATION_long); const bool up = (plica->GetDir() == STEMDIRECTION_basic_up); int shape = LIGATURE_DEFAULT; @@ -722,7 +722,7 @@ data_STEMDIRECTION View::GetMensuralStemDir(Layer *layer, Note *note, int vertic stemDir = layerStemDir; } else { - if (drawingDur < DUR_1) { + if (drawingDur < DURATION_1) { stemDir = STEMDIRECTION_down; } else { diff --git a/src/view_tab.cpp b/src/view_tab.cpp index dd28a98fe09..6fa926578e3 100644 --- a/src/view_tab.cpp +++ b/src/view_tab.cpp @@ -177,13 +177,13 @@ void View::DrawTabDurSym(DeviceContext *dc, LayerElement *element, Layer *layer, if (!tabGrp->IsInBeam() && !staff->IsTabGuitar()) { int symc = 0; switch (drawingDur) { - case DUR_1: symc = SMUFL_EBA6_luteDurationDoubleWhole; break; // 1 back flag */ - case DUR_2: symc = SMUFL_EBA7_luteDurationWhole; break; // 0 flags - case DUR_4: symc = SMUFL_EBA8_luteDurationHalf; break; // 1 flag - case DUR_8: symc = SMUFL_EBA9_luteDurationQuarter; break; // 2 flags - case DUR_16: symc = SMUFL_EBAA_luteDuration8th; break; // 3 flags - case DUR_32: symc = SMUFL_EBAB_luteDuration16th; break; // 4 flags - case DUR_64: symc = SMUFL_EBAC_luteDuration32nd; break; // 5 flags + case DURATION_1: symc = SMUFL_EBA6_luteDurationDoubleWhole; break; // 1 back flag */ + case DURATION_2: symc = SMUFL_EBA7_luteDurationWhole; break; // 0 flags + case DURATION_4: symc = SMUFL_EBA8_luteDurationHalf; break; // 1 flag + case DURATION_8: symc = SMUFL_EBA9_luteDurationQuarter; break; // 2 flags + case DURATION_16: symc = SMUFL_EBAA_luteDuration8th; break; // 3 flags + case DURATION_32: symc = SMUFL_EBAB_luteDuration16th; break; // 4 flags + case DURATION_64: symc = SMUFL_EBAC_luteDuration32nd; break; // 5 flags default: symc = SMUFL_EBA9_luteDurationQuarter; // 2 flags } @@ -205,9 +205,11 @@ void View::DrawTabDurSym(DeviceContext *dc, LayerElement *element, Layer *layer, } else { // Vertical: the more flags the lower the dots - const int durfactor = DUR_64 - std::min(std::max(drawingDur, DUR_2), DUR_64) + 1; - static_assert(DUR_64 - DUR_2 + 1 == 6); - static_assert(DUR_64 - DUR_64 + 1 == 1); + int durOffset = (drawingDur > DURATION_2) ? drawingDur : DURATION_2; + durOffset = (durOffset < DURATION_64) ? durOffset : DURATION_64; + const int durfactor = DURATION_64 - durOffset + 1; + static_assert(DURATION_64 - DURATION_2 + 1 == 6); + static_assert(DURATION_64 - DURATION_64 + 1 == 1); y += m_doc->GetDrawingUnit(glyphSize) * stemDirFactor * durfactor * 2 / 5; From d4ddb7a34fd293693a3e7113ea39308381f8191c Mon Sep 17 00:00:00 2001 From: Laurent Pugin Date: Thu, 3 Oct 2024 14:27:41 +0200 Subject: [PATCH 05/25] Additional change to data_DURATION type --- include/vrv/durationinterface.h | 8 ++++---- src/durationinterface.cpp | 25 +++++++++++++------------ src/view_element.cpp | 4 ++-- 3 files changed, 19 insertions(+), 18 deletions(-) diff --git a/include/vrv/durationinterface.h b/include/vrv/durationinterface.h index b52e34d8953..4265aedcfd7 100644 --- a/include/vrv/durationinterface.h +++ b/include/vrv/durationinterface.h @@ -89,15 +89,15 @@ class DurationInterface : public Interface, * For mensural, we need to apply the DUR_MENSURAL_MASK */ ///@{ - int GetActualDur() const; - int GetActualDurGes() const; + data_DURATION GetActualDur() const; + data_DURATION GetActualDurGes() const; ///@} /** * If the element is part of a chord, return the chord actual duration, otherwise the note actual duration. * Since we need to check what the element is, we need to pass it as parameter. */ - int GetNoteOrChordDur(const LayerElement *element) const; + data_DURATION GetNoteOrChordDur(const LayerElement *element) const; /** * Return true if the value is a mensural (DURATION_longa, brevis, etc.) @@ -141,7 +141,7 @@ class DurationInterface : public Interface, /** * Calculate the actual duration => translate mensural values */ - int CalcActualDur(data_DURATION dur) const; + data_DURATION CalcActualDur(data_DURATION dur) const; public: // diff --git a/src/durationinterface.cpp b/src/durationinterface.cpp index e39fad14f98..07aafa0f0c8 100644 --- a/src/durationinterface.cpp +++ b/src/durationinterface.cpp @@ -74,8 +74,8 @@ void DurationInterface::Reset() Fraction DurationInterface::GetInterfaceAlignmentDuration(int num, int numBase) const { - int noteDur = this->GetDurGes() != DURATION_NONE ? this->GetActualDurGes() : this->GetActualDur(); - if (noteDur == DUR_NONE) noteDur = DURATION_4; + data_DURATION noteDur = (this->GetDurGes() != DURATION_NONE) ? this->GetActualDurGes() : this->GetActualDur(); + if (noteDur == DURATION_NONE) noteDur = DURATION_4; if (this->HasNum()) num *= this->GetNum(); if (this->HasNumbase()) numBase *= this->GetNumbase(); @@ -93,7 +93,7 @@ Fraction DurationInterface::GetInterfaceAlignmentDuration(int num, int numBase) double DurationInterface::GetInterfaceAlignmentMensuralDuration(int num, int numBase, const Mensur *currentMensur) const { int noteDur = this->GetDurGes() != DURATION_NONE ? this->GetActualDurGes() : this->GetActualDur(); - if (noteDur == DUR_NONE) noteDur = DURATION_4; + if (noteDur == DURATION_NONE) noteDur = DURATION_4; if (!currentMensur) { LogWarning("No current mensur for calculating duration"); @@ -174,36 +174,37 @@ bool DurationInterface::IsLastInBeam(const LayerElement *noteOrRest) const return (noteOrRest == beam->GetListBack()); } -int DurationInterface::GetActualDur() const +data_DURATION DurationInterface::GetActualDur() const { const data_DURATION dur = this->HasDur() ? this->GetDur() : this->GetDurDefault(); return this->CalcActualDur(dur); } -int DurationInterface::GetActualDurGes() const +data_DURATION DurationInterface::GetActualDurGes() const { const data_DURATION dur = this->HasDurGes() ? this->GetDurGes() : DURATION_NONE; return this->CalcActualDur(dur); } -int DurationInterface::CalcActualDur(data_DURATION dur) const +data_DURATION DurationInterface::CalcActualDur(data_DURATION dur) const { - if (dur == DURATION_NONE) return DUR_NONE; + if (dur == DURATION_NONE) return DURATION_NONE; // maxima (-1) is a mensural only value if (dur == DURATION_maxima) return DURATION_maxima; - return (dur & DUR_MENSURAL_MASK); + // return (dur & DUR_MENSURAL_MASK); + return DURATION_breve; } -int DurationInterface::GetNoteOrChordDur(const LayerElement *element) const +data_DURATION DurationInterface::GetNoteOrChordDur(const LayerElement *element) const { if (element->Is(CHORD)) { - int duration = this->GetActualDur(); - if (duration != DUR_NONE) return duration; + data_DURATION duration = this->GetActualDur(); + if (duration != DURATION_NONE) return duration; const Chord *chord = vrv_cast(element); for (const Note *note : { chord->GetTopNote(), chord->GetBottomNote() }) { duration = note->GetActualDur(); - if (duration != DUR_NONE) { + if (duration != DURATION_NONE) { return duration; } } diff --git a/src/view_element.cpp b/src/view_element.cpp index 0f15863eab9..fe041d76cc4 100644 --- a/src/view_element.cpp +++ b/src/view_element.cpp @@ -1455,7 +1455,7 @@ void View::DrawNote(DeviceContext *dc, LayerElement *element, Layer *layer, Staf if (!(note->GetHeadVisible() == BOOLEAN_false)) { /************** Noteheads: **************/ int drawingDur = note->GetDrawingDur(); - if (drawingDur == DUR_NONE) { + if (drawingDur == DURATION_NONE) { if (note->IsInBeam() && !dc->Is(BBOX_DEVICE_CONTEXT)) { LogWarning("Missing duration for note '%s' in beam", note->GetID().c_str()); } @@ -1540,7 +1540,7 @@ void View::DrawRest(DeviceContext *dc, LayerElement *element, Layer *layer, Staf const bool drawingCueSize = rest->GetDrawingCueSize(); const int staffSize = staff->GetDrawingStaffNotationSize(); int drawingDur = rest->GetActualDur(); - if (drawingDur == DUR_NONE) { + if (drawingDur == DURATION_NONE) { if (!dc->Is(BBOX_DEVICE_CONTEXT)) { LogWarning("Missing duration for rest '%s'", rest->GetID().c_str()); } From be38fd1e445f408316d2dfb201ff1e432326c369 Mon Sep 17 00:00:00 2001 From: Laurent Pugin Date: Thu, 3 Oct 2024 16:08:21 +0200 Subject: [PATCH 06/25] Change durations from int to data_DURATION for better typing * 2 static_cast left in BeamSegment::AdjustBeamToFrenchStyle * 1 static_cast left in BeamSegment::CalcStemDefiningNote --- include/vrv/beam.h | 4 ++-- include/vrv/calcalignmentxposfunctor.h | 4 ++-- include/vrv/calcstemfunctor.h | 4 ++-- include/vrv/drawinginterface.h | 2 +- include/vrv/note.h | 4 ++-- include/vrv/rest.h | 2 +- include/vrv/vrv.h | 7 ++++++ src/beam.cpp | 33 ++++++++++++++------------ src/calcalignmentxposfunctor.cpp | 2 +- src/calcligatureorneumeposfunctor.cpp | 4 ++-- src/calcstemfunctor.cpp | 2 +- src/drawinginterface.cpp | 6 ++--- src/durationinterface.cpp | 16 +++++++++---- src/layerelement.cpp | 4 ++-- src/note.cpp | 6 ++--- src/page.cpp | 2 +- src/preparedatafunctor.cpp | 2 +- src/rest.cpp | 4 ++-- src/view_beam.cpp | 6 ++--- src/view_element.cpp | 6 ++--- src/view_mensural.cpp | 6 ++--- src/vrv.cpp | 10 ++++++++ 22 files changed, 82 insertions(+), 54 deletions(-) diff --git a/include/vrv/beam.h b/include/vrv/beam.h index 5ae37892360..855d556417d 100644 --- a/include/vrv/beam.h +++ b/include/vrv/beam.h @@ -156,7 +156,7 @@ class BeamSegment { int CalcMixedBeamCenterY(int step, int unit) const; // Helper to calculate location and duration of the note that would be setting highest/lowest point for the beam - std::tuple CalcStemDefiningNote(const Staff *staff, data_BEAMPLACE place) const; + std::tuple CalcStemDefiningNote(const Staff *staff, data_BEAMPLACE place) const; // Calculate positioning for the horizontal beams void CalcHorizontalBeam(const Doc *doc, const Staff *staff, const BeamDrawingInterface *beamInterface); @@ -454,7 +454,7 @@ class BeamElementCoord { int m_x; int m_yBeam; // y value of stem top position - int m_dur; // drawing duration + data_DURATION m_dur; // drawing duration int m_breaksec; int m_overlapMargin; int m_maxShortening; // maximum allowed shortening in half units diff --git a/include/vrv/calcalignmentxposfunctor.h b/include/vrv/calcalignmentxposfunctor.h index 5eda96449a8..2680dc611e5 100644 --- a/include/vrv/calcalignmentxposfunctor.h +++ b/include/vrv/calcalignmentxposfunctor.h @@ -40,7 +40,7 @@ class CalcAlignmentXPosFunctor : public DocFunctor { */ ///@{ int GetLongestActualDur() const { return m_longestActualDur; } - void SetLongestActualDur(int dur) { m_longestActualDur = dur; } + void SetLongestActualDur(data_DURATION dur) { m_longestActualDur = dur; } ///@} /* @@ -65,7 +65,7 @@ class CalcAlignmentXPosFunctor : public DocFunctor { // The previous x rel position int m_previousXRel; // Duration of the longest note - int m_longestActualDur; + data_DURATION m_longestActualDur; // The estimated justification ratio of the system double m_estimatedJustificationRatio; // The last alignment that was not timestamp-only diff --git a/include/vrv/calcstemfunctor.h b/include/vrv/calcstemfunctor.h index ee414083668..c90f8db60a8 100644 --- a/include/vrv/calcstemfunctor.h +++ b/include/vrv/calcstemfunctor.h @@ -62,7 +62,7 @@ class CalcStemFunctor : public DocFunctor { * Adjusts the flag placement and stem length if they are crossing notehead or ledger lines */ void AdjustFlagPlacement( - const Doc *doc, Stem *stem, Flag *flag, int staffSize, int verticalCenter, int duration) const; + const Doc *doc, Stem *stem, Flag *flag, int staffSize, int verticalCenter, data_DURATION duration) const; public: // @@ -72,7 +72,7 @@ class CalcStemFunctor : public DocFunctor { // The vertical center of the staff int m_verticalCenter; // The actual duration of the chord / note - int m_dur; + data_DURATION m_dur; // The flag for grace notes (stem is not extended) bool m_isGraceNote; // The flag for stem.sameas notes diff --git a/include/vrv/drawinginterface.h b/include/vrv/drawinginterface.h index 32d2e88e253..49b85b6c421 100644 --- a/include/vrv/drawinginterface.h +++ b/include/vrv/drawinginterface.h @@ -186,7 +186,7 @@ class BeamDrawingInterface : public ObjectListInterface { Staff *m_crossStaffContent; data_STAFFREL_basic m_crossStaffRel; bool m_isSpanningElement; - int m_shortestDur; + data_DURATION m_shortestDur; data_STEMDIRECTION m_notesStemDir; data_BEAMPLACE m_drawingPlace; Staff *m_beamStaff; diff --git a/include/vrv/note.h b/include/vrv/note.h index b6b8261ac6f..2ab4cc48bcf 100644 --- a/include/vrv/note.h +++ b/include/vrv/note.h @@ -146,7 +146,7 @@ class Note : public LayerElement, ///@{ Chord *IsChordTone(); const Chord *IsChordTone() const; - int GetDrawingDur() const; + data_DURATION GetDrawingDur() const; bool IsNoteGroupExtreme() const; // used to find if it is the highest or lowest note in a note group ///@} @@ -211,7 +211,7 @@ class Note : public LayerElement, /** * Return a SMuFL code for the notehead */ - char32_t GetNoteheadGlyph(const int duration) const; + char32_t GetNoteheadGlyph(const data_DURATION duration) const; /** * Check whether current note is enharmonic with another diff --git a/include/vrv/rest.h b/include/vrv/rest.h index b737eebc0d7..506df84a891 100644 --- a/include/vrv/rest.h +++ b/include/vrv/rest.h @@ -84,7 +84,7 @@ class Rest : public LayerElement, */ ///@{ char32_t GetRestGlyph() const; - char32_t GetRestGlyph(const int duration) const; + char32_t GetRestGlyph(const data_DURATION duration) const; ///@} /** diff --git a/include/vrv/vrv.h b/include/vrv/vrv.h index d103807cd37..9a8a80937cf 100644 --- a/include/vrv/vrv.h +++ b/include/vrv/vrv.h @@ -22,6 +22,7 @@ #include #endif +#include "attdef.h" #include "atttypes.h" #include "toolkitdef.h" @@ -131,6 +132,12 @@ std::string FromCamelCase(const std::string &s); */ std::string ToCamelCase(const std::string &s); +/* + * Min / Max for data_DURATION (std::min/max not possible) + */ +data_DURATION DurationMin(data_DURATION dur1, data_DURATION dur2); +data_DURATION DurationMax(data_DURATION dur1, data_DURATION dur2); + /** * */ diff --git a/src/beam.cpp b/src/beam.cpp index 297674fe23a..8eddeb4968a 100644 --- a/src/beam.cpp +++ b/src/beam.cpp @@ -457,7 +457,7 @@ void BeamSegment::AdjustBeamToFrenchStyle(const BeamDrawingInterface *beamInterf assert(beamInterface); // set to store durations of relevant notes (it's ordered, so min duration is going to be first) - std::set noteDurations; + std::set noteDurations; // lambda check whether coord has element set and whether that element is CHORD or NOTE const auto isNoteOrChord = [](BeamElementCoord *coord) { return (coord->m_element && coord->m_element->Is({ CHORD, NOTE })); }; @@ -470,7 +470,9 @@ void BeamSegment::AdjustBeamToFrenchStyle(const BeamDrawingInterface *beamInterf if (!isNoteOrChord(*it)) continue; // get current element duration - const int val = (*it)->m_breaksec ? std::min((*it)->m_breaksec + DURATION_4, (*it)->m_dur) : (*it)->m_dur; + const data_DURATION val = (*it)->m_breaksec + ? vrv::DurationMin(static_cast((*it)->m_breaksec + DURATION_4), (*it)->m_dur) + : (*it)->m_dur; noteDurations.insert(val); // get next element duration CoordIt nextElement = std::find_if(it + 1, m_beamElementCoordRefs.end(), isNoteOrChord); @@ -481,8 +483,9 @@ void BeamSegment::AdjustBeamToFrenchStyle(const BeamDrawingInterface *beamInterf CoordReverseIt reverse = std::make_reverse_iterator(it); CoordReverseIt prevElement = std::find_if(reverse, m_beamElementCoordRefs.rend(), isNoteOrChord); if (prevElement != m_beamElementCoordRefs.rend()) { - const int prevVal = (*prevElement)->m_breaksec - ? std::min((*prevElement)->m_breaksec + DURATION_4, (*prevElement)->m_dur) + const data_DURATION prevVal = (*prevElement)->m_breaksec + ? vrv::DurationMin( + static_cast((*prevElement)->m_breaksec + DURATION_4), (*prevElement)->m_dur) : (*prevElement)->m_dur; noteDurations.insert(prevVal); } @@ -884,7 +887,7 @@ int BeamSegment::CalcBeamSlopeStep( } // duration - const int dur = beamInterface->m_shortestDur; + const data_DURATION dur = beamInterface->m_shortestDur; // Prevent short step with values not shorter than a 16th if (shortStep && (dur >= DURATION_32)) { step = unit * 2; @@ -1212,7 +1215,7 @@ void BeamSegment::CalcBeamStemLength(const Staff *staff, data_BEAMPLACE place, b // skip current element if it's longer that minDuration and is not a part of fTrem if ((coord->m_dur < noteDur) && !(coord->m_element && coord->m_element->GetFirstAncestor(FTREM))) continue; // adjust stem length if location matches - const int dur = (preferredDur != 0) ? preferredDur : coord->m_dur; + const data_DURATION dur = (preferredDur != 0) ? preferredDur : coord->m_dur; const int coordStemLength = coord->CalculateStemLength(staff, stemDir, isHorizontal, dur); if (coord->m_closestNote->GetDrawingLoc() == noteLoc) { m_uniformStemLength = coordStemLength; @@ -1266,11 +1269,11 @@ int BeamSegment::CalcMixedBeamCenterY(int step, int unit) const return centerY; } -std::tuple BeamSegment::CalcStemDefiningNote(const Staff *staff, data_BEAMPLACE place) const +std::tuple BeamSegment::CalcStemDefiningNote(const Staff *staff, data_BEAMPLACE place) const { - int shortestDuration = DURATION_4; + data_DURATION shortestDuration = DURATION_4; int shortestLoc = VRV_UNSET; - int relevantDuration = DURATION_4; + data_DURATION relevantDuration = DURATION_4; int relevantLoc = VRV_UNSET; const data_STEMDIRECTION globalStemDir = (place == BEAMPLACE_below) ? STEMDIRECTION_down : STEMDIRECTION_up; for (BeamElementCoord *coord : m_beamElementCoordRefs) { @@ -1313,7 +1316,7 @@ std::tuple BeamSegment::CalcStemDefiningNote(const Staff *staff, } } - int adjusted_duration = 0; + data_DURATION adjusted_duration = DURATION_NONE; // if shortest note location does not offset its duration (shorter notes need more space for additional beams) then // give preference to the its location if ((shortestDuration - relevantDuration) > (std::abs(relevantLoc - shortestLoc) + 1)) { @@ -1328,7 +1331,7 @@ std::tuple BeamSegment::CalcStemDefiningNote(const Staff *staff, } } else if ((shortestDuration - relevantDuration) == std::abs(relevantLoc - shortestLoc)) { - adjusted_duration = (relevantDuration + shortestDuration) / 2; + adjusted_duration = static_cast((relevantDuration + shortestDuration) / 2); } return { relevantLoc, relevantDuration, adjusted_duration }; @@ -2081,14 +2084,14 @@ void BeamElementCoord::UpdateStemLength( std::pair Beam::GetAdditionalBeamCount() const { - int topShortestDur = DURATION_8; - int bottomShortestDur = DURATION_8; + data_DURATION topShortestDur = DURATION_8; + data_DURATION bottomShortestDur = DURATION_8; std::for_each(m_beamElementCoords.begin(), m_beamElementCoords.end(), [&](BeamElementCoord *coord) { if (coord->m_partialFlagPlace == BEAMPLACE_above) { - topShortestDur = std::max(topShortestDur, coord->m_dur); + topShortestDur = vrv::DurationMax(topShortestDur, coord->m_dur); } else if (coord->m_partialFlagPlace == BEAMPLACE_below) { - bottomShortestDur = std::max(bottomShortestDur, coord->m_dur); + bottomShortestDur = vrv::DurationMax(bottomShortestDur, coord->m_dur); } }); diff --git a/src/calcalignmentxposfunctor.cpp b/src/calcalignmentxposfunctor.cpp index cad0ee57f3d..1aaf14eeddc 100644 --- a/src/calcalignmentxposfunctor.cpp +++ b/src/calcalignmentxposfunctor.cpp @@ -24,7 +24,7 @@ CalcAlignmentXPosFunctor::CalcAlignmentXPosFunctor(Doc *doc) : DocFunctor(doc) { m_previousTime = 0.0; m_previousXRel = 0; - m_longestActualDur = 0; + m_longestActualDur = DURATION_NONE; m_estimatedJustificationRatio = 1.0; m_lastNonTimestamp = NULL; m_measureAligner = NULL; diff --git a/src/calcligatureorneumeposfunctor.cpp b/src/calcligatureorneumeposfunctor.cpp index 5fb5576ff4f..4ed08423439 100644 --- a/src/calcligatureorneumeposfunctor.cpp +++ b/src/calcligatureorneumeposfunctor.cpp @@ -62,8 +62,8 @@ FunctorCode CalcLigatureOrNeumePosFunctor::VisitLigature(Ligature *ligature) // Look at the @lig attribute on the previous note if (previousNote->GetLig() == LIGATUREFORM_obliqua) oblique = true; - int dur1 = previousNote->GetActualDur(); - int dur2 = note->GetActualDur(); + data_DURATION dur1 = previousNote->GetActualDur(); + data_DURATION dur2 = note->GetActualDur(); // Same treatment for Mx and LG except for positioning, which is done above // We still need to avoid oblique, so keep a flag. bool isMaxima = false; diff --git a/src/calcstemfunctor.cpp b/src/calcstemfunctor.cpp index c5f483ddb31..17a65040e5a 100644 --- a/src/calcstemfunctor.cpp +++ b/src/calcstemfunctor.cpp @@ -621,7 +621,7 @@ data_STEMDIRECTION CalcStemFunctor::CalcStemDirection(const Chord *chord, int ve } void CalcStemFunctor::AdjustFlagPlacement( - const Doc *doc, Stem *stem, Flag *flag, int staffSize, int verticalCenter, int duration) const + const Doc *doc, Stem *stem, Flag *flag, int staffSize, int verticalCenter, data_DURATION duration) const { assert(stem->GetParent()); assert(stem->GetParent()->IsLayerElement()); diff --git a/src/drawinginterface.cpp b/src/drawinginterface.cpp index d4be4bf9d35..facd2c57737 100644 --- a/src/drawinginterface.cpp +++ b/src/drawinginterface.cpp @@ -94,7 +94,7 @@ void BeamDrawingInterface::Reset() m_crossStaffContent = NULL; m_crossStaffRel = STAFFREL_basic_NONE; m_isSpanningElement = false; - m_shortestDur = 0; + m_shortestDur = DURATION_NONE; m_notesStemDir = STEMDIRECTION_NONE; m_drawingPlace = BEAMPLACE_NONE; m_beamStaff = NULL; @@ -148,7 +148,7 @@ void BeamDrawingInterface::InitCoords(const ListOfObjects &childList, Staff *sta // Beam list should contain only DurationInterface objects assert(current->GetDurationInterface()); - int lastDur = (current->GetDurationInterface())->GetActualDur(); + data_DURATION lastDur = (current->GetDurationInterface())->GetActualDur(); /******************************************************************/ // Populate BeamElementCoord for each element in the beam @@ -164,7 +164,7 @@ void BeamDrawingInterface::InitCoords(const ListOfObjects &childList, Staff *sta do { // Beam list should contain only DurationInterface objects assert(current->GetDurationInterface()); - const int currentDur = (current->GetDurationInterface())->GetActualDur(); + const data_DURATION currentDur = (current->GetDurationInterface())->GetActualDur(); if (current->Is(CHORD)) { m_beamHasChord = true; diff --git a/src/durationinterface.cpp b/src/durationinterface.cpp index 07aafa0f0c8..e6675538482 100644 --- a/src/durationinterface.cpp +++ b/src/durationinterface.cpp @@ -188,11 +188,19 @@ data_DURATION DurationInterface::GetActualDurGes() const data_DURATION DurationInterface::CalcActualDur(data_DURATION dur) const { - if (dur == DURATION_NONE) return DURATION_NONE; // maxima (-1) is a mensural only value - if (dur == DURATION_maxima) return DURATION_maxima; - // return (dur & DUR_MENSURAL_MASK); - return DURATION_breve; + if (dur < DUR_MAX) return dur; + // Mensural duration (except maxima) + switch (dur) { + case (DURATION_longa): return DURATION_long; + case (DURATION_brevis): return DURATION_breve; + case (DURATION_semibrevis): return DURATION_1; + case (DURATION_minima): return DURATION_2; + case (DURATION_semiminima): return DURATION_4; + case (DURATION_fusa): return DURATION_8; + case (DURATION_semifusa): return DURATION_16; + default: return DURATION_NONE; + } } data_DURATION DurationInterface::GetNoteOrChordDur(const LayerElement *element) const diff --git a/src/layerelement.cpp b/src/layerelement.cpp index 3a0f99bb6e2..cd6c0da8a44 100644 --- a/src/layerelement.cpp +++ b/src/layerelement.cpp @@ -616,7 +616,7 @@ int LayerElement::GetDrawingRadius(const Doc *doc, bool isInLigature) const if (!this->Is({ CHORD, NC, NOTE, REST })) return 0; char32_t code = 0; - int dur = DURATION_4; + data_DURATION dur = DURATION_4; const Staff *staff = this->GetAncestorStaff(); bool isMensuralDur = false; if (this->Is(NOTE)) { @@ -1200,7 +1200,7 @@ std::pair LayerElement::CalcElementHorizontalOverlap(const Doc *doc, isUnisonElement = currentNote->IsUnisonWith(previousNote, true); // Unisson, look at the duration for the note heads if (unison && currentNote->IsUnisonWith(previousNote, false)) { - int previousDuration = previousNote->GetDrawingDur(); + data_DURATION previousDuration = previousNote->GetDrawingDur(); assert(previousNote->GetParent()); const bool isPreviousChord = previousNote->GetParent()->Is(CHORD); bool isEdgeElement = false; diff --git a/src/note.cpp b/src/note.cpp index 1037dd17315..54af2ee5695 100644 --- a/src/note.cpp +++ b/src/note.cpp @@ -239,7 +239,7 @@ const Chord *Note::IsChordTone() const return vrv_cast(this->GetFirstAncestor(CHORD, MAX_CHORD_DEPTH)); } -int Note::GetDrawingDur() const +data_DURATION Note::GetDrawingDur() const { const Chord *chordParent = vrv_cast(this->GetFirstAncestor(CHORD, MAX_CHORD_DEPTH)); if (chordParent && !this->HasDur()) { @@ -491,7 +491,7 @@ char32_t Note::GetMensuralNoteheadGlyph() const { assert(this->IsMensuralDur()); - int drawingDur = this->GetDrawingDur(); + data_DURATION drawingDur = this->GetDrawingDur(); // No SMuFL code used for these values if (drawingDur < DURATION_1) { @@ -526,7 +526,7 @@ char32_t Note::GetMensuralNoteheadGlyph() const return code; } -char32_t Note::GetNoteheadGlyph(const int duration) const +char32_t Note::GetNoteheadGlyph(const data_DURATION duration) const { static std::map additionalNoteheadSymbols = { { "noteheadDiamondBlackWide", SMUFL_E0DC_noteheadDiamondBlackWide }, diff --git a/src/page.cpp b/src/page.cpp index cab9e92fea6..a5de8172a24 100644 --- a/src/page.cpp +++ b/src/page.cpp @@ -318,7 +318,7 @@ void Page::ResetAligners() // Unless duration-based spacing is disabled, set the X position of each Alignment. // Does non-linear spacing based on the duration space between two Alignment objects. if (!doc->GetOptions()->m_evenNoteSpacing.GetValue()) { - int longestActualDur = DURATION_4; + data_DURATION longestActualDur = DURATION_4; // Detect the longest duration in order to adjust the spacing (false by default) if (doc->GetOptions()->m_spacingDurDetection.GetValue()) { diff --git a/src/preparedatafunctor.cpp b/src/preparedatafunctor.cpp index 091b6be6d54..8666862c692 100644 --- a/src/preparedatafunctor.cpp +++ b/src/preparedatafunctor.cpp @@ -1101,7 +1101,7 @@ FunctorCode PrepareLayerElementPartsFunctor::VisitChord(Chord *chord) currentStem->AttGraced::operator=(*chord); currentStem->FillAttributes(*chord); - int duration = chord->GetNoteOrChordDur(chord); + data_DURATION duration = chord->GetNoteOrChordDur(chord); if ((duration < DURATION_2) || (chord->GetStemVisible() == BOOLEAN_false)) { currentStem->IsVirtual(true); } diff --git a/src/rest.cpp b/src/rest.cpp index 444159f8e63..323cb970a86 100644 --- a/src/rest.cpp +++ b/src/rest.cpp @@ -244,7 +244,7 @@ char32_t Rest::GetRestGlyph() const return this->GetRestGlyph(this->GetActualDur()); } -char32_t Rest::GetRestGlyph(const int duration) const +char32_t Rest::GetRestGlyph(const data_DURATION duration) const { const Resources *resources = this->GetDocResources(); if (!resources) return 0; @@ -559,7 +559,7 @@ int Rest::GetMarginLayerLocation(bool isTopLayer, bool restOverlap) const int Rest::GetRestOffsetFromOptions( RestLayer layer, const std::pair &location, bool isTopLayer) const { - int duration = this->GetActualDur(); + data_DURATION duration = this->GetActualDur(); // Make sure we are in the boundaries of g_defaultRests if (duration > DURATION_128) duration = DURATION_128; if (duration < DURATION_long) duration = DURATION_long; diff --git a/src/view_beam.cpp b/src/view_beam.cpp index 566234d1cc3..046e24e190e 100644 --- a/src/view_beam.cpp +++ b/src/view_beam.cpp @@ -150,7 +150,7 @@ void View::DrawFTremSegment(DeviceContext *dc, Staff *staff, FTrem *fTrem) // We look only at the first one for the duration since both are expected to be the same AttDurationLog *durationElement = dynamic_cast(firstElement->m_element); if (!durationElement) return; - const int dur = durationElement->GetDur(); + const data_DURATION dur = durationElement->GetDur(); if (dur > DURATION_1) { // Adjust the x position of the first and last element for taking into account the stem width @@ -289,8 +289,8 @@ void View::DrawBeamSegment( } int noteCount = (int)noteIndexes.size(); - int durRef = DURATION_8; - int durRef2 = DURATION_16; + data_DURATION durRef = DURATION_8; + data_DURATION durRef2 = DURATION_16; if (staff->IsTabLuteFrench() || staff->IsTabLuteItalian()) { durRef = DURATION_4; diff --git a/src/view_element.cpp b/src/view_element.cpp index fe041d76cc4..b6bf6101623 100644 --- a/src/view_element.cpp +++ b/src/view_element.cpp @@ -275,7 +275,7 @@ void View::DrawAccid(DeviceContext *dc, LayerElement *element, Layer *layer, Sta // look at the note position and adjust it if necessary Note *note = vrv_cast(accid->GetFirstAncestor(NOTE, MAX_ACCID_DEPTH)); if (note) { - const int drawingDur = note->GetDrawingDur(); + const data_DURATION drawingDur = note->GetDrawingDur(); int noteTop = note->GetDrawingTop(m_doc, staff->m_drawingStaffSize); int noteBottom = note->GetDrawingBottom(m_doc, staff->m_drawingStaffSize); bool onStaff = (accid->GetOnstaff() == BOOLEAN_true); @@ -1454,7 +1454,7 @@ void View::DrawNote(DeviceContext *dc, LayerElement *element, Layer *layer, Staf if (!(note->GetHeadVisible() == BOOLEAN_false)) { /************** Noteheads: **************/ - int drawingDur = note->GetDrawingDur(); + data_DURATION drawingDur = note->GetDrawingDur(); if (drawingDur == DURATION_NONE) { if (note->IsInBeam() && !dc->Is(BBOX_DEVICE_CONTEXT)) { LogWarning("Missing duration for note '%s' in beam", note->GetID().c_str()); @@ -1539,7 +1539,7 @@ void View::DrawRest(DeviceContext *dc, LayerElement *element, Layer *layer, Staf const bool drawingCueSize = rest->GetDrawingCueSize(); const int staffSize = staff->GetDrawingStaffNotationSize(); - int drawingDur = rest->GetActualDur(); + data_DURATION drawingDur = rest->GetActualDur(); if (drawingDur == DURATION_NONE) { if (!dc->Is(BBOX_DEVICE_CONTEXT)) { LogWarning("Missing duration for rest '%s'", rest->GetID().c_str()); diff --git a/src/view_mensural.cpp b/src/view_mensural.cpp index a02bc5f9cad..5222b8d916d 100644 --- a/src/view_mensural.cpp +++ b/src/view_mensural.cpp @@ -50,7 +50,7 @@ void View::DrawMensuralNote(DeviceContext *dc, LayerElement *element, Layer *lay const int yNote = element->GetDrawingY(); const int xNote = element->GetDrawingX(); - const int drawingDur = note->GetDrawingDur(); + const data_DURATION drawingDur = note->GetDrawingDur(); /************** Noteheads: **************/ @@ -161,7 +161,7 @@ void View::DrawMensuralStem(DeviceContext *dc, Note *note, Staff *staff, data_ST assert(note); const int staffSize = staff->m_drawingStaffSize; - const int drawingDur = note->GetDrawingDur(); + const data_DURATION drawingDur = note->GetDrawingDur(); const int radius = note->GetDrawingRadius(m_doc); // Cue size is currently disabled const bool drawingCueSize = false; @@ -710,7 +710,7 @@ void View::CalcObliquePoints(Note *note1, Note *note2, Staff *staff, Point point data_STEMDIRECTION View::GetMensuralStemDir(Layer *layer, Note *note, int verticalCenter) { // constants - const int drawingDur = note->GetDrawingDur(); + const data_DURATION drawingDur = note->GetDrawingDur(); const int yNote = note->GetDrawingY(); data_STEMDIRECTION layerStemDir; diff --git a/src/vrv.cpp b/src/vrv.cpp index 06340f6ecff..2378a542dd8 100644 --- a/src/vrv.cpp +++ b/src/vrv.cpp @@ -459,6 +459,16 @@ std::string ToCamelCase(const std::string &s) return result; } +data_DURATION DurationMin(data_DURATION dur1, data_DURATION dur2) +{ + return (dur1 < dur2) ? dur1 : dur2; +} + +data_DURATION DurationMax(data_DURATION dur1, data_DURATION dur2) +{ + return (dur1 > dur2) ? dur1 : dur2; +} + //---------------------------------------------------------------------------- // Notation type checks //---------------------------------------------------------------------------- From f0b477e59b9b5491600eed290e88f369fa2c0c15 Mon Sep 17 00:00:00 2001 From: Laurent Pugin Date: Thu, 3 Oct 2024 16:13:14 +0200 Subject: [PATCH 07/25] Fix missing switch default and remove () --- src/durationinterface.cpp | 14 +++++++------- src/rest.cpp | 2 ++ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/durationinterface.cpp b/src/durationinterface.cpp index e6675538482..24297314f3a 100644 --- a/src/durationinterface.cpp +++ b/src/durationinterface.cpp @@ -192,13 +192,13 @@ data_DURATION DurationInterface::CalcActualDur(data_DURATION dur) const if (dur < DUR_MAX) return dur; // Mensural duration (except maxima) switch (dur) { - case (DURATION_longa): return DURATION_long; - case (DURATION_brevis): return DURATION_breve; - case (DURATION_semibrevis): return DURATION_1; - case (DURATION_minima): return DURATION_2; - case (DURATION_semiminima): return DURATION_4; - case (DURATION_fusa): return DURATION_8; - case (DURATION_semifusa): return DURATION_16; + case DURATION_longa: return DURATION_long; + case DURATION_brevis: return DURATION_breve; + case DURATION_semibrevis: return DURATION_1; + case DURATION_minima: return DURATION_2; + case DURATION_semiminima: return DURATION_4; + case DURATION_fusa: return DURATION_8; + case DURATION_semifusa: return DURATION_16; default: return DURATION_NONE; } } diff --git a/src/rest.cpp b/src/rest.cpp index 323cb970a86..7e622d604d1 100644 --- a/src/rest.cpp +++ b/src/rest.cpp @@ -270,6 +270,7 @@ char32_t Rest::GetRestGlyph(const data_DURATION duration) const case DURATION_4: return SMUFL_E9F6_mensuralRestSemiminima; break; case DURATION_8: return SMUFL_E9F7_mensuralRestFusa; break; case DURATION_16: return SMUFL_E9F8_mensuralRestSemifusa; break; + default: return 0; } } else { @@ -287,6 +288,7 @@ char32_t Rest::GetRestGlyph(const data_DURATION duration) const case DURATION_256: return SMUFL_E4EB_rest256th; break; case DURATION_512: return SMUFL_E4EC_rest512th; break; case DURATION_1024: return SMUFL_E4ED_rest1024th; break; + default: return 0; } } From 99717d5529929e35bc9030d09a271a7de42d6ad6 Mon Sep 17 00:00:00 2001 From: Laurent Pugin Date: Thu, 3 Oct 2024 16:14:29 +0200 Subject: [PATCH 08/25] Add Fraction constructor from data_DURATION --- include/vrv/horizontalaligner.h | 1 + src/durationinterface.cpp | 2 ++ src/horizontalaligner.cpp | 8 ++++++++ 3 files changed, 11 insertions(+) diff --git a/include/vrv/horizontalaligner.h b/include/vrv/horizontalaligner.h index efa5a210895..824cfa6b7ba 100644 --- a/include/vrv/horizontalaligner.h +++ b/include/vrv/horizontalaligner.h @@ -69,6 +69,7 @@ class Fraction { public: // Constructors Fraction(int num = 0, int denom = 1); + Fraction(data_DURATION duration); /** Addition operator */ Fraction operator+(const Fraction &other) const; diff --git a/src/durationinterface.cpp b/src/durationinterface.cpp index 24297314f3a..75a42299beb 100644 --- a/src/durationinterface.cpp +++ b/src/durationinterface.cpp @@ -80,6 +80,8 @@ Fraction DurationInterface::GetInterfaceAlignmentDuration(int num, int numBase) if (this->HasNum()) num *= this->GetNum(); if (this->HasNumbase()) numBase *= this->GetNumbase(); + // Fraction duration(noteDur); + // duration = duration * numBase / num; Fraction duration = DUR_MAX / pow(2.0, (double)(noteDur - 2.0)) * numBase / num; int noteDots = (this->HasDotsGes()) ? this->GetDotsGes() : this->GetDots(); diff --git a/src/horizontalaligner.cpp b/src/horizontalaligner.cpp index 8315fabfaee..955443e5ab9 100644 --- a/src/horizontalaligner.cpp +++ b/src/horizontalaligner.cpp @@ -47,6 +47,14 @@ Fraction::Fraction(int num, int denom) : m_numerator(num), m_denominator(denom) Reduce(); } +Fraction::Fraction(data_DURATION duration) +{ + int den = pow(2, (duration + 1)); + m_numerator = 8; + m_denominator = den; + Reduce(); +} + Fraction Fraction::operator+(const Fraction &other) const { int num = m_numerator * other.m_denominator + other.m_numerator * m_denominator; From 9c71347f0c576958171cd41d116d0f9257bedaf4 Mon Sep 17 00:00:00 2001 From: Laurent Pugin Date: Thu, 3 Oct 2024 16:44:12 +0200 Subject: [PATCH 09/25] Fix regression on grace note stems --- include/vrv/beam.h | 3 ++- src/beam.cpp | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/include/vrv/beam.h b/include/vrv/beam.h index 855d556417d..2ab3afd24cc 100644 --- a/include/vrv/beam.h +++ b/include/vrv/beam.h @@ -429,7 +429,8 @@ class BeamElementCoord { void SetClosestNoteOrTabDurSym(data_STEMDIRECTION stemDir, bool outsideStaff); /** Helper for calculating the stem length for staff notation and tablature beams within the staff */ - int CalculateStemLength(const Staff *staff, data_STEMDIRECTION stemDir, bool isHorizontal, int preferredDur) const; + int CalculateStemLength( + const Staff *staff, data_STEMDIRECTION stemDir, bool isHorizontal, data_DURATION preferredDur) const; /** Helper for calculating the stem length for tablature beam placed outside the staff */ int CalculateStemLengthTab(const Staff *staff, data_STEMDIRECTION stemDir) const; diff --git a/src/beam.cpp b/src/beam.cpp index 8eddeb4968a..5cffc7fb905 100644 --- a/src/beam.cpp +++ b/src/beam.cpp @@ -1215,7 +1215,7 @@ void BeamSegment::CalcBeamStemLength(const Staff *staff, data_BEAMPLACE place, b // skip current element if it's longer that minDuration and is not a part of fTrem if ((coord->m_dur < noteDur) && !(coord->m_element && coord->m_element->GetFirstAncestor(FTREM))) continue; // adjust stem length if location matches - const data_DURATION dur = (preferredDur != 0) ? preferredDur : coord->m_dur; + const data_DURATION dur = (preferredDur != DURATION_NONE) ? preferredDur : coord->m_dur; const int coordStemLength = coord->CalculateStemLength(staff, stemDir, isHorizontal, dur); if (coord->m_closestNote->GetDrawingLoc() == noteLoc) { m_uniformStemLength = coordStemLength; @@ -1942,7 +1942,7 @@ void BeamElementCoord::SetDrawingStemDir(data_STEMDIRECTION stemDir, const Staff } int BeamElementCoord::CalculateStemLength( - const Staff *staff, data_STEMDIRECTION stemDir, bool isHorizontal, int preferredDur) const + const Staff *staff, data_STEMDIRECTION stemDir, bool isHorizontal, data_DURATION preferredDur) const { if (!m_closestNote) return 0; From 0e76a16e4dac51aae56aeca6e18ea248534c1257 Mon Sep 17 00:00:00 2001 From: Laurent Pugin Date: Thu, 3 Oct 2024 19:37:55 +0200 Subject: [PATCH 10/25] Change alignment to Fraction with whole note == 1/1 --- include/vrv/beatrpt.h | 2 +- include/vrv/durationinterface.h | 2 +- include/vrv/horizontalaligner.h | 24 +++++++++++++++++------- include/vrv/metersig.h | 6 ++++++ include/vrv/timestamp.h | 2 +- src/alignfunctor.cpp | 10 ++++++---- src/beatrpt.cpp | 8 ++++---- src/calcalignmentxposfunctor.cpp | 10 +++++----- src/durationinterface.cpp | 17 ++++++++++------- src/findlayerelementsfunctor.cpp | 4 ++-- src/horizontalaligner.cpp | 23 ++++++++++++----------- src/layerelement.cpp | 27 ++++++++++----------------- src/metersig.cpp | 13 +++++++++++++ src/timestamp.cpp | 5 +++-- src/view_control.cpp | 4 ++-- 15 files changed, 93 insertions(+), 64 deletions(-) diff --git a/include/vrv/beatrpt.h b/include/vrv/beatrpt.h index d4d8a4d9b5d..8db95215c38 100644 --- a/include/vrv/beatrpt.h +++ b/include/vrv/beatrpt.h @@ -43,7 +43,7 @@ class BeatRpt : public LayerElement, public AttColor, public AttBeatRptLog, publ * Returns the duration (in double) for the BeatRpt. */ - double GetBeatRptAlignmentDuration(int meterUnit) const; + Fraction GetBeatRptAlignmentDuration(data_DURATION meterUnit) const; /** * MIDI timing information diff --git a/include/vrv/durationinterface.h b/include/vrv/durationinterface.h index 4265aedcfd7..b1cd3d3760c 100644 --- a/include/vrv/durationinterface.h +++ b/include/vrv/durationinterface.h @@ -70,7 +70,7 @@ class DurationInterface : public Interface, * Currently this assume brevis equality (through DUR_MENSURAL_REF) and would * need to be modified for shorter equality in later repertoire. */ - double GetInterfaceAlignmentMensuralDuration(int num, int numBase, const Mensur *currentMensur) const; + Fraction GetInterfaceAlignmentMensuralDuration(int num, int numBase, const Mensur *currentMensur) const; /** * Return true if the note or rest is the first of a beam. diff --git a/include/vrv/horizontalaligner.h b/include/vrv/horizontalaligner.h index 824cfa6b7ba..d28fa25c731 100644 --- a/include/vrv/horizontalaligner.h +++ b/include/vrv/horizontalaligner.h @@ -67,9 +67,15 @@ enum AlignmentType { class Fraction { public: - // Constructors - Fraction(int num = 0, int denom = 1); - Fraction(data_DURATION duration); + // Constructors - make them explicit to avoid type conversion + explicit Fraction(int num = 0, int denom = 1); + explicit Fraction(data_DURATION duration); + + // Enable implicit conversion constructor for `int` + template >> + Fraction(T num) : m_numerator(num), m_denominator(1) + { + } /** Addition operator */ Fraction operator+(const Fraction &other) const; @@ -91,6 +97,10 @@ class Fraction { /** Greater than or equal operator */ bool operator>=(const Fraction &other) const; + /** Getters */ + int GetNumerator() const { return m_numerator; } + int GetDenominator() const { return m_denominator; } + /** Convert fraction to a double */ double ToDouble() const; @@ -261,7 +271,7 @@ class Alignment : public Object { * formula with parameters can come close and has other advantages. */ static int HorizontalSpaceForDuration( - const Fraction &intervalTime, int maxActualDur, double spacingLinear, double spacingNonLinear); + const Fraction &intervalTime, data_DURATION maxActualDur, double spacingLinear, double spacingNonLinear); //----------// // Functors // @@ -507,8 +517,8 @@ class MeasureAligner : public HorizontalAligner { * Setter takes a meter unit parameter. */ ///@{ - void SetInitialTstamp(int meterUnit); - double GetInitialTstampDur() const { return m_initialTstampDur; } + void SetInitialTstamp(data_DURATION meterUnit); + Fraction GetInitialTstampDur() const { return m_initialTstampDur; } ///@} /** @@ -593,7 +603,7 @@ class MeasureAligner : public HorizontalAligner { * The time duration of the timestamp between 0.0 and 1.0. * This depends on the meter signature in the preceeding scoreDef */ - double m_initialTstampDur; + Fraction m_initialTstampDur; }; //---------------------------------------------------------------------------- diff --git a/include/vrv/metersig.h b/include/vrv/metersig.h index 585c259b9c4..4e3363e4863 100644 --- a/include/vrv/metersig.h +++ b/include/vrv/metersig.h @@ -54,6 +54,12 @@ class MeterSig : public LayerElement, /** Evaluate additive meter counts */ int GetTotalCount() const; + /** + * Return the unit (int) as data_DURATION (up to 32). + * Return DURATION_4 if no match. + */ + data_DURATION GetUnitAsDur() const; + /** Retrieves the symbol glyph */ char32_t GetSymbolGlyph() const; diff --git a/include/vrv/timestamp.h b/include/vrv/timestamp.h index c715b569ec0..fe537184dad 100644 --- a/include/vrv/timestamp.h +++ b/include/vrv/timestamp.h @@ -41,7 +41,7 @@ class TimestampAttr : public LayerElement { /** * Returns the duration (in double) for the Timestamp. */ - double GetTimestampAttrAlignmentDuration(int meterUnit) const; + Fraction GetTimestampAttrAlignmentDuration(data_DURATION meterUnit) const; //----------// // Functors // diff --git a/src/alignfunctor.cpp b/src/alignfunctor.cpp index fad1c8874f4..4dd8fe4a3ca 100644 --- a/src/alignfunctor.cpp +++ b/src/alignfunctor.cpp @@ -40,7 +40,7 @@ namespace vrv { AlignHorizontallyFunctor::AlignHorizontallyFunctor(Doc *doc) : DocFunctor(doc) { m_measureAligner = NULL; - m_time = 0.0; + m_time = 0; m_currentParams.mensur = NULL; m_currentParams.meterSig = NULL; m_notationType = NOTATIONTYPE_cmn; @@ -56,7 +56,7 @@ FunctorCode AlignHorizontallyFunctor::VisitLayer(Layer *layer) // We are starting a new layer, reset the time; // We set it to -1.0 for the scoreDef attributes since they have to be aligned before any timestamp event (-1.0) - m_time = DUR_MAX * -1.0; + m_time = -1; m_scoreDefRole = m_isFirstMeasure ? SCOREDEF_SYSTEM : SCOREDEF_INTERMEDIATE; @@ -87,7 +87,7 @@ FunctorCode AlignHorizontallyFunctor::VisitLayer(Layer *layer) m_scoreDefRole = SCOREDEF_NONE; // Now we have to set it to 0.0 since we will start aligning musical content - m_time = 0.0; + m_time = 0; return FUNCTOR_CONTINUE; } @@ -378,7 +378,9 @@ FunctorCode AlignHorizontallyFunctor::VisitMeasure(Measure *measure) FunctorCode AlignHorizontallyFunctor::VisitMeasureEnd(Measure *measure) { - int meterUnit = m_currentParams.meterSig ? m_currentParams.meterSig->GetUnit() : 4; + data_DURATION meterUnit = (m_currentParams.meterSig && m_currentParams.meterSig->HasUnit()) + ? m_currentParams.meterSig->GetUnitAsDur() + : DURATION_4; measure->m_measureAligner.SetInitialTstamp(meterUnit); // We also need to align the timestamps - we do it at the end since we need the *meterSig to be initialized by a diff --git a/src/beatrpt.cpp b/src/beatrpt.cpp index 3b72624333c..26dc321bc07 100644 --- a/src/beatrpt.cpp +++ b/src/beatrpt.cpp @@ -54,11 +54,11 @@ void BeatRpt::Reset() m_scoreTimeOnset = 0.0; } -double BeatRpt::GetBeatRptAlignmentDuration(int meterUnit) const +Fraction BeatRpt::GetBeatRptAlignmentDuration(data_DURATION meterUnit) const { - double dur = DUR_MAX / meterUnit; - if (this->HasBeatdef()) dur *= this->GetBeatdef(); - return dur; + Fraction duration(meterUnit); + if (this->HasBeatdef()) duration = duration * Fraction(this->GetBeatdef() * DUR_MAX, DUR_MAX); + return duration; } void BeatRpt::SetScoreTimeOnset(double scoreTime) diff --git a/src/calcalignmentxposfunctor.cpp b/src/calcalignmentxposfunctor.cpp index 1aaf14eeddc..6f8c291dc8e 100644 --- a/src/calcalignmentxposfunctor.cpp +++ b/src/calcalignmentxposfunctor.cpp @@ -22,7 +22,7 @@ namespace vrv { CalcAlignmentXPosFunctor::CalcAlignmentXPosFunctor(Doc *doc) : DocFunctor(doc) { - m_previousTime = 0.0; + m_previousTime = 0; m_previousXRel = 0; m_longestActualDur = DURATION_NONE; m_estimatedJustificationRatio = 1.0; @@ -39,7 +39,7 @@ FunctorCode CalcAlignmentXPosFunctor::VisitAlignment(Alignment *alignment) Fraction intervalTime = alignment->GetTime() - m_previousTime; if (alignment->GetType() > ALIGNMENT_MEASURE_RIGHT_BARLINE) { - intervalTime = 0.0; + intervalTime = 0; } // Do not move aligners that are only time-stamps at this stage but add it to the pending list @@ -48,7 +48,7 @@ FunctorCode CalcAlignmentXPosFunctor::VisitAlignment(Alignment *alignment) return FUNCTOR_CONTINUE; } - if (intervalTime > 0.0) { + if (intervalTime > 0) { intervalXRel = Alignment::HorizontalSpaceForDuration(intervalTime, m_longestActualDur, m_doc->GetOptions()->m_spacingLinear.GetValue(), m_doc->GetOptions()->m_spacingNonLinear.GetValue()); // LogDebug("CalcAlignmentXPos: intervalTime=%.2f intervalXRel=%d", intervalTime, intervalXRel); @@ -81,7 +81,7 @@ FunctorCode CalcAlignmentXPosFunctor::VisitAlignment(Alignment *alignment) // For each timestamp alignment, move them proportionally to the space we currently have for (auto &tsAlignment : m_timestamps) { // Avoid division by zero (nothing to move with the alignment anyway - if (duration == 0.0) break; + if (duration == 0) break; Fraction percent = (tsAlignment->GetTime() - startTime) / duration; tsAlignment->SetXRel(startXRel + space * percent.ToDouble()); } @@ -98,7 +98,7 @@ FunctorCode CalcAlignmentXPosFunctor::VisitMeasure(Measure *measure) { // We start a new Measure // Reset the previous time position and x_rel to 0; - m_previousTime = 0.0; + m_previousTime = 0; // We un-measured music we never have a left barline, so do not add a default space m_previousXRel = (measure->IsMeasuredMusic()) ? m_doc->GetDrawingUnit(100) : 0; diff --git a/src/durationinterface.cpp b/src/durationinterface.cpp index 75a42299beb..68c05cea91e 100644 --- a/src/durationinterface.cpp +++ b/src/durationinterface.cpp @@ -80,26 +80,29 @@ Fraction DurationInterface::GetInterfaceAlignmentDuration(int num, int numBase) if (this->HasNum()) num *= this->GetNum(); if (this->HasNumbase()) numBase *= this->GetNumbase(); - // Fraction duration(noteDur); - // duration = duration * numBase / num; - Fraction duration = DUR_MAX / pow(2.0, (double)(noteDur - 2.0)) * numBase / num; + Fraction duration(noteDur); + duration = duration * numBase / num; + // double old = DUR_MAX / pow(2.0, (double)(noteDur - 2.0)) * numBase / num; + // duration = DUR_MAX / pow(2.0, (double)(noteDur - 2.0)) * numBase / num; int noteDots = (this->HasDotsGes()) ? this->GetDotsGes() : this->GetDots(); if (noteDots != VRV_UNSET) { - duration = duration * 2 - (duration / pow(2, noteDots)); + Fraction durationReduction(duration.GetNumerator(), duration.GetDenominator() * pow(2, noteDots)); + duration = duration * 2 - durationReduction; } // LogDebug("Duration %d; Dot %d; Alignment %f", noteDur, this->GetDots(), duration); return duration; } -double DurationInterface::GetInterfaceAlignmentMensuralDuration(int num, int numBase, const Mensur *currentMensur) const +Fraction DurationInterface::GetInterfaceAlignmentMensuralDuration( + int num, int numBase, const Mensur *currentMensur) const { int noteDur = this->GetDurGes() != DURATION_NONE ? this->GetActualDurGes() : this->GetActualDur(); if (noteDur == DURATION_NONE) noteDur = DURATION_4; if (!currentMensur) { LogWarning("No current mensur for calculating duration"); - return DUR_MENSURAL_REF; + return Fraction(1, 1); } if (this->HasNum() || this->HasNumbase()) { @@ -155,7 +158,7 @@ double DurationInterface::GetInterfaceAlignmentMensuralDuration(int num, int num duration *= (double)numBase / (double)num; // LogDebug("Duration %d; %d/%d; Alignment %f; Ratio %f", noteDur, num, numbase, duration, ratio); duration = durRound(duration); - return duration; + return Fraction(DUR_MAX * duration, DUR_MAX * DUR_MAX); } bool DurationInterface::IsFirstInBeam(const LayerElement *noteOrRest) const diff --git a/src/findlayerelementsfunctor.cpp b/src/findlayerelementsfunctor.cpp index 0ebba8830fa..35129d8b0af 100644 --- a/src/findlayerelementsfunctor.cpp +++ b/src/findlayerelementsfunctor.cpp @@ -90,8 +90,8 @@ LayerElementsInTimeSpanFunctor::LayerElementsInTimeSpanFunctor( const MeterSig *meterSig, const Mensur *mensur, const Layer *layer) : ConstFunctor() { - m_time = 0.0; - m_duration = 0.0; + m_time = 0; + m_duration = 0; m_meterParams.meterSig = meterSig; m_meterParams.mensur = mensur; m_layer = layer; diff --git a/src/horizontalaligner.cpp b/src/horizontalaligner.cpp index 955443e5ab9..8cbf97a20ab 100644 --- a/src/horizontalaligner.cpp +++ b/src/horizontalaligner.cpp @@ -49,6 +49,8 @@ Fraction::Fraction(int num, int denom) : m_numerator(num), m_denominator(denom) Fraction::Fraction(data_DURATION duration) { + duration = vrv::DurationMin(duration, DURATION_1024); + duration = vrv::DurationMax(duration, DURATION_NONE); int den = pow(2, (duration + 1)); m_numerator = 8; m_denominator = den; @@ -232,16 +234,16 @@ void MeasureAligner::Reset() { HorizontalAligner::Reset(); m_nonJustifiableLeftMargin = 0; - m_leftAlignment = new Alignment(-1.0 * DUR_MAX, ALIGNMENT_MEASURE_START); + m_leftAlignment = new Alignment(-1, ALIGNMENT_MEASURE_START); AddAlignment(m_leftAlignment); - m_leftBarLineAlignment = new Alignment(-1.0 * DUR_MAX, ALIGNMENT_MEASURE_LEFT_BARLINE); + m_leftBarLineAlignment = new Alignment(-1, ALIGNMENT_MEASURE_LEFT_BARLINE); AddAlignment(m_leftBarLineAlignment); - m_rightBarLineAlignment = new Alignment(0.0 * DUR_MAX, ALIGNMENT_MEASURE_RIGHT_BARLINE); + m_rightBarLineAlignment = new Alignment(0, ALIGNMENT_MEASURE_RIGHT_BARLINE); AddAlignment(m_rightBarLineAlignment); - m_rightAlignment = new Alignment(0.0 * DUR_MAX, ALIGNMENT_MEASURE_END); + m_rightAlignment = new Alignment(0, ALIGNMENT_MEASURE_END); AddAlignment(m_rightAlignment); - m_initialTstampDur = -DUR_MAX; + m_initialTstampDur = -1; } bool MeasureAligner::IsSupportedChild(Object *child) @@ -302,11 +304,9 @@ Fraction MeasureAligner::GetMaxTime() const return m_rightAlignment->GetTime(); } -void MeasureAligner::SetInitialTstamp(int meterUnit) +void MeasureAligner::SetInitialTstamp(data_DURATION meterUnit) { - if (meterUnit != 0) { - m_initialTstampDur = DUR_MAX / meterUnit * -1; - } + m_initialTstampDur = Fraction(meterUnit) * -1; } void MeasureAligner::AdjustProportionally(const ArrayOfAdjustmentTuples &adjustments) @@ -836,14 +836,15 @@ std::pair Alignment::GetAlignmentTopBottom() const } int Alignment::HorizontalSpaceForDuration( - const Fraction &intervalTime, int maxActualDur, double spacingLinear, double spacingNonLinear) + const Fraction &intervalTime, data_DURATION maxActualDur, double spacingLinear, double spacingNonLinear) { double doubleIntervalTime = intervalTime.ToDouble(); /* If the longest duration interval in the score is longer than semibreve, adjust spacing so that interval gets the space a semibreve would ordinarily get. */ if (maxActualDur < DURATION_1) doubleIntervalTime /= pow(2.0, DURATION_1 - maxActualDur); - return pow(doubleIntervalTime, spacingNonLinear) * spacingLinear * 10.0; // numbers are experimental constants + return pow(doubleIntervalTime * 1024, spacingNonLinear) * spacingLinear + * 10.0; // numbers are experimental constants } FunctorCode Alignment::Accept(Functor &functor) diff --git a/src/layerelement.cpp b/src/layerelement.cpp index cd6c0da8a44..20f59628df1 100644 --- a/src/layerelement.cpp +++ b/src/layerelement.cpp @@ -76,11 +76,9 @@ namespace vrv { // MAX_DURATION / pow(2.0, (DURATION_4 - 2.0)) #define NEUME_LARGE_SPACE 256 // Medium spacing between neume is a 8th note space -// MAX_DURATION / pow(2.0, (DUR_5 - 2.0)) -#define NEUME_MEDIUM_SPACE 128 +#define NEUME_MEDIUM_SPACE Fraction(1, 8) // Small spacing between neume components is a 16th note space -// MAX_DURATION / pow(2.0, (DUR_6 - 2.0)) -#define NEUME_SMALL_SPACE 64 +#define NEUME_SMALL_SPACE Fraction(1, 16) //---------------------------------------------------------------------------- // LayerElement @@ -730,30 +728,25 @@ Fraction LayerElement::GetAlignmentDuration( else if (this->Is(BEATRPT)) { const BeatRpt *beatRpt = vrv_cast(this); assert(beatRpt); - int meterUnit = 4; - if (params.meterSig && params.meterSig->HasUnit()) meterUnit = params.meterSig->GetUnit(); + data_DURATION meterUnit = DURATION_4; + if (params.meterSig && params.meterSig->HasUnit()) meterUnit = params.meterSig->GetUnitAsDur(); return beatRpt->GetBeatRptAlignmentDuration(meterUnit); } else if (this->Is(TIMESTAMP_ATTR)) { const TimestampAttr *timestampAttr = vrv_cast(this); assert(timestampAttr); - int meterUnit = 4; - if (params.meterSig && params.meterSig->HasUnit()) meterUnit = params.meterSig->GetUnit(); + data_DURATION meterUnit = DURATION_4; + if (params.meterSig && params.meterSig->HasUnit()) meterUnit = params.meterSig->GetUnitAsDur(); return timestampAttr->GetTimestampAttrAlignmentDuration(meterUnit); } // We align all full measure element to the current time signature, even the ones that last longer than one measure else if (this->Is({ HALFMRPT, MREST, MULTIREST, MRPT, MRPT2, MULTIRPT })) { - int meterUnit = 4; + data_DURATION meterUnit = DURATION_4; int meterCount = 4; - if (params.meterSig && params.meterSig->HasUnit()) meterUnit = params.meterSig->GetUnit(); + if (params.meterSig && params.meterSig->HasUnit()) meterUnit = params.meterSig->GetUnitAsDur(); if (params.meterSig && params.meterSig->HasCount()) meterCount = params.meterSig->GetTotalCount(); - - if (this->Is(HALFMRPT)) { - return (DUR_MAX / meterUnit * meterCount) / 2; - } - else { - return DUR_MAX / meterUnit * meterCount; - } + Fraction duration = Fraction(meterUnit) * meterCount; + return (this->Is(HALFMRPT)) ? (duration / 2) : duration; } // This is not called with --neume-as-note since otherwise each nc has an aligner else if (this->Is(NEUME)) { diff --git a/src/metersig.cpp b/src/metersig.cpp index f3df8054d23..8ff16ecf702 100644 --- a/src/metersig.cpp +++ b/src/metersig.cpp @@ -108,6 +108,19 @@ int MeterSig::GetTotalCount() const return counts.front(); } +data_DURATION MeterSig::GetUnitAsDur() const +{ + switch (this->GetUnit()) { + case 1: return DURATION_1; + case 2: return DURATION_2; + case 4: return DURATION_4; + case 8: return DURATION_8; + case 16: return DURATION_16; + case 32: return DURATION_32; + default: return DURATION_4; + } +} + char32_t MeterSig::GetSymbolGlyph() const { char32_t glyph = 0; diff --git a/src/timestamp.cpp b/src/timestamp.cpp index da4a52e682d..c7bd31c6269 100644 --- a/src/timestamp.cpp +++ b/src/timestamp.cpp @@ -35,9 +35,10 @@ void TimestampAttr::Reset() m_actualDurPos = 0.0; } -double TimestampAttr::GetTimestampAttrAlignmentDuration(int meterUnit) const +Fraction TimestampAttr::GetTimestampAttrAlignmentDuration(data_DURATION meterUnit) const { - return DUR_MAX / meterUnit * m_actualDurPos; + Fraction duration(meterUnit); + return (duration * Fraction(m_actualDurPos * DUR_MAX, DUR_MAX)); } FunctorCode TimestampAttr::Accept(Functor &functor) diff --git a/src/view_control.cpp b/src/view_control.cpp index 9a0065f0ce9..6c908fb21ff 100644 --- a/src/view_control.cpp +++ b/src/view_control.cpp @@ -1269,8 +1269,8 @@ void View::DrawSylConnector( } // We are in the system of the last note - draw the connector from the beginning of the system else if (spanningType == SPANNING_END) { - // If we do not want to show hyphens at the start of a system and the end is at time 0.0 - if (m_options->m_lyricNoStartHyphen.GetValue() && (syl->GetEnd()->GetAlignment()->GetTime() == 0.0)) { + // If we do not want to show hyphens at the start of a system and the end is at time 0 + if (m_options->m_lyricNoStartHyphen.GetValue() && (syl->GetEnd()->GetAlignment()->GetTime() == 0)) { // Return but only if the end is in the first measure of the system... Measure *measure = vrv_cast(syl->GetEnd()->GetFirstAncestor(MEASURE)); assert(measure); From 1274b14a4785531f5a402293cecb443b45cd69a6 Mon Sep 17 00:00:00 2001 From: Laurent Pugin Date: Thu, 3 Oct 2024 20:04:09 +0200 Subject: [PATCH 11/25] Fix comments --- include/vrv/beatrpt.h | 2 +- include/vrv/durationinterface.h | 2 +- include/vrv/timestamp.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/vrv/beatrpt.h b/include/vrv/beatrpt.h index 8db95215c38..bf892e589c0 100644 --- a/include/vrv/beatrpt.h +++ b/include/vrv/beatrpt.h @@ -40,7 +40,7 @@ class BeatRpt : public LayerElement, public AttColor, public AttBeatRptLog, publ bool HasToBeAligned() const override { return true; } /** - * Returns the duration (in double) for the BeatRpt. + * Returns the duration (in Fraction) for the BeatRpt. */ Fraction GetBeatRptAlignmentDuration(data_DURATION meterUnit) const; diff --git a/include/vrv/durationinterface.h b/include/vrv/durationinterface.h index b1cd3d3760c..215ba4fce57 100644 --- a/include/vrv/durationinterface.h +++ b/include/vrv/durationinterface.h @@ -66,7 +66,7 @@ class DurationInterface : public Interface, Fraction GetInterfaceAlignmentDuration(int num, int numBase) const; /** - * Returns the duration (in double) for the element for mensural notation + * Returns the duration (in Fraction) for the element for mensural notation * Currently this assume brevis equality (through DUR_MENSURAL_REF) and would * need to be modified for shorter equality in later repertoire. */ diff --git a/include/vrv/timestamp.h b/include/vrv/timestamp.h index fe537184dad..71e208592c9 100644 --- a/include/vrv/timestamp.h +++ b/include/vrv/timestamp.h @@ -39,7 +39,7 @@ class TimestampAttr : public LayerElement { ///@} /** - * Returns the duration (in double) for the Timestamp. + * Returns the duration (in Fraction) for the Timestamp. */ Fraction GetTimestampAttrAlignmentDuration(data_DURATION meterUnit) const; From 6ba605205e29e59d9099f1d845cb2d02415633eb Mon Sep 17 00:00:00 2001 From: Laurent Pugin Date: Thu, 3 Oct 2024 20:58:34 +0200 Subject: [PATCH 12/25] Remove call to Fraction::ToDouble --- src/alignfunctor.cpp | 2 -- src/view_element.cpp | 8 +++----- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/src/alignfunctor.cpp b/src/alignfunctor.cpp index 4dd8fe4a3ca..f28c7badeda 100644 --- a/src/alignfunctor.cpp +++ b/src/alignfunctor.cpp @@ -310,8 +310,6 @@ FunctorCode AlignHorizontallyFunctor::VisitLayerElement(LayerElement *layerEleme // get the duration of the event duration = layerElement->GetAlignmentDuration(m_currentParams, true, m_notationType); - // LogDebug("duration %s %f", duration.ToString().c_str(), duration.ToDouble()); - // For timestamp, what we get from GetAlignmentDuration is actually the position of the timestamp // So use it as current time - we can do this because the timestamp loop is redirected from the measure // The time will be reset to 0.0 when starting a new layer anyway diff --git a/src/view_element.cpp b/src/view_element.cpp index b6bf6101623..9766eac5833 100644 --- a/src/view_element.cpp +++ b/src/view_element.cpp @@ -1165,11 +1165,9 @@ void View::DrawMRest(DeviceContext *dc, LayerElement *element, Layer *layer, Sta const bool drawingCueSize = mRest->GetDrawingCueSize(); int x = mRest->GetDrawingX(); - int y = (measure->m_measureAligner.GetMaxTime().ToDouble() >= (DUR_MAX * 2)) - ? element->GetDrawingY() - m_doc->GetDrawingDoubleUnit(staffSize) - : element->GetDrawingY(); - char32_t rest = (measure->m_measureAligner.GetMaxTime().ToDouble() >= (DUR_MAX * 2)) ? SMUFL_E4E2_restDoubleWhole - : SMUFL_E4E3_restWhole; + const bool isDouble = (measure->m_measureAligner.GetMaxTime() >= Fraction(2, 1)); + int y = isDouble ? element->GetDrawingY() - m_doc->GetDrawingDoubleUnit(staffSize) : element->GetDrawingY(); + char32_t rest = isDouble ? SMUFL_E4E2_restDoubleWhole : SMUFL_E4E3_restWhole; x -= m_doc->GetGlyphWidth(rest, staffSize, drawingCueSize) / 2; From 94d345392b431c7ea7cae6005f0e8dbec56cccc4 Mon Sep 17 00:00:00 2001 From: Laurent Pugin Date: Thu, 3 Oct 2024 21:12:11 +0200 Subject: [PATCH 13/25] Change beam pattern detection items --- src/drawinginterface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/drawinginterface.cpp b/src/drawinginterface.cpp index facd2c57737..c4a102a9432 100644 --- a/src/drawinginterface.cpp +++ b/src/drawinginterface.cpp @@ -421,7 +421,7 @@ bool BeamDrawingInterface::IsRepeatedPattern() const if (!coord->m_stem || !coord->m_closestNote) continue; // Could this be an overflow with 32 bits? - items.push_back(coord->m_closestNote->GetDrawingY() * DUR_MAX + coord->m_dur); + items.push_back(coord->m_closestNote->GetDrawingY() + DUR_MAX * coord->m_dur); } int itemCount = (int)items.size(); From e76c57963b832ccdbcdea5255c212f578ac8db38 Mon Sep 17 00:00:00 2001 From: Laurent Pugin Date: Thu, 3 Oct 2024 21:12:45 +0200 Subject: [PATCH 14/25] Remove unnecessary defines --- libmei/addons/attdef.h | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/libmei/addons/attdef.h b/libmei/addons/attdef.h index d04af822ac6..6bb21ecd9b7 100644 --- a/libmei/addons/attdef.h +++ b/libmei/addons/attdef.h @@ -33,12 +33,6 @@ typedef double data_VU; // Durations //---------------------------------------------------------------------------- -/** - * These duration values are used for internal calculation and differ from the - * MEI data.DURATION types (see below) - */ -#define DUR_NONE -32 -#define DUR_MX -1 // maxima // used for alignement #define DUR_MAX 1024 // mensural duration @@ -88,13 +82,13 @@ typedef std::vector> data_BULGE; * MEI data.DURATION */ enum data_DURATION { - DURATION_NONE = DUR_NONE, - DURATION_maxima = DUR_MX, - DURATION_long, + DURATION_NONE = -2, + DURATION_maxima, // -1 + DURATION_long, // 0 DURATION_breve, DURATION_1, DURATION_2, - DURATION_4, + DURATION_4, // 4 DURATION_8, DURATION_16, DURATION_32, From 406044ddd05c852efeb54e7d6e2429391d8b20a2 Mon Sep 17 00:00:00 2001 From: Laurent Pugin Date: Thu, 3 Oct 2024 21:14:27 +0200 Subject: [PATCH 15/25] Rename variable --- src/horizontalaligner.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/horizontalaligner.cpp b/src/horizontalaligner.cpp index 8cbf97a20ab..7b440275c51 100644 --- a/src/horizontalaligner.cpp +++ b/src/horizontalaligner.cpp @@ -838,13 +838,12 @@ std::pair Alignment::GetAlignmentTopBottom() const int Alignment::HorizontalSpaceForDuration( const Fraction &intervalTime, data_DURATION maxActualDur, double spacingLinear, double spacingNonLinear) { - double doubleIntervalTime = intervalTime.ToDouble(); + double intervalTimeDbl = intervalTime.ToDouble(); /* If the longest duration interval in the score is longer than semibreve, adjust spacing so that interval gets the space a semibreve would ordinarily get. */ - if (maxActualDur < DURATION_1) doubleIntervalTime /= pow(2.0, DURATION_1 - maxActualDur); + if (maxActualDur < DURATION_1) intervalTimeDbl /= pow(2.0, DURATION_1 - maxActualDur); - return pow(doubleIntervalTime * 1024, spacingNonLinear) * spacingLinear - * 10.0; // numbers are experimental constants + return pow(intervalTimeDbl * 1024, spacingNonLinear) * spacingLinear * 10.0; // numbers are experimental constants } FunctorCode Alignment::Accept(Functor &functor) From d677d5bd789970a4d7e88acfc0188a7120954904 Mon Sep 17 00:00:00 2001 From: Laurent Pugin Date: Fri, 4 Oct 2024 10:53:16 +0200 Subject: [PATCH 16/25] Add method to convert Fraction to data_DURATION * Used in PAE output --- include/vrv/horizontalaligner.h | 3 +++ libmei/addons/attdef.h | 2 +- src/horizontalaligner.cpp | 15 +++++++++++++++ src/iopae.cpp | 7 ++++--- 4 files changed, 23 insertions(+), 4 deletions(-) diff --git a/include/vrv/horizontalaligner.h b/include/vrv/horizontalaligner.h index d28fa25c731..25ca888dbb3 100644 --- a/include/vrv/horizontalaligner.h +++ b/include/vrv/horizontalaligner.h @@ -107,6 +107,9 @@ class Fraction { /** Convert fraction to a string */ std::string ToString() const; + /** Convert to data_DURATION and the remaining Fraction */ + std::pair ToDur() const; + private: /** Reduce the fraction */ void Reduce(); diff --git a/libmei/addons/attdef.h b/libmei/addons/attdef.h index 6bb21ecd9b7..1bbd8de2975 100644 --- a/libmei/addons/attdef.h +++ b/libmei/addons/attdef.h @@ -96,7 +96,7 @@ enum data_DURATION { DURATION_128, DURATION_256, DURATION_512, - DURATION_1024, + DURATION_1024, // 12 DURATION_2048, DURATION_longa = DUR_MENSURAL_OFFSET + DURATION_long, DURATION_brevis, diff --git a/src/horizontalaligner.cpp b/src/horizontalaligner.cpp index 7b440275c51..f1a68746279 100644 --- a/src/horizontalaligner.cpp +++ b/src/horizontalaligner.cpp @@ -135,6 +135,21 @@ void Fraction::Reduce() m_denominator /= gcdVal; } +std::pair Fraction::ToDur() const +{ + if (m_numerator == 0) return { DURATION_NONE, 0 }; + + int value = ceil(log2((double)m_denominator / (double)m_numerator * 8)) - 1; + data_DURATION dur = static_cast(value); + dur = vrv::DurationMax(DURATION_maxima, dur); + dur = vrv::DurationMin(DURATION_2048, dur); + + Fraction remainder = *this - Fraction(dur); + // Making sure we would not be trigger an inifite loop when looping over the remainder + if ((remainder >= *this) || (remainder < 0)) remainder = 0; + return { dur, remainder }; +} + //---------------------------------------------------------------------------- // HorizontalAligner //---------------------------------------------------------------------------- diff --git a/src/iopae.cpp b/src/iopae.cpp index 5c654356e48..2106985c027 100644 --- a/src/iopae.cpp +++ b/src/iopae.cpp @@ -521,10 +521,11 @@ void PAEOutput::WriteTuplet(Tuplet *tuplet) Staff *staff = tuplet->GetAncestorStaff(); - double content = tuplet->GetContentAlignmentDuration(true, staff->m_drawingNotationType).ToDouble(); - // content = DUR_MAX / 2^(dur - 2) - int tupletDur = (content != 0.0) ? log2(DUR_MAX / content) + 2 : 4; + auto [tupletDur, remainder] = tuplet->GetContentAlignmentDuration(true, staff->m_drawingNotationType).ToDur(); // We should be looking for dotted values + if (remainder != 0) { + LogWarning("The tuplet content is not a single non-dotted duration"); + } std::string dur; switch (tupletDur) { From 6697cece6b66b8651dbb25310e11d4c9a0e3e636 Mon Sep 17 00:00:00 2001 From: Laurent Pugin Date: Fri, 4 Oct 2024 13:44:40 +0200 Subject: [PATCH 17/25] Adjust variable --- src/calcalignmentxposfunctor.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/calcalignmentxposfunctor.cpp b/src/calcalignmentxposfunctor.cpp index 6f8c291dc8e..38e992e3741 100644 --- a/src/calcalignmentxposfunctor.cpp +++ b/src/calcalignmentxposfunctor.cpp @@ -82,8 +82,8 @@ FunctorCode CalcAlignmentXPosFunctor::VisitAlignment(Alignment *alignment) for (auto &tsAlignment : m_timestamps) { // Avoid division by zero (nothing to move with the alignment anyway if (duration == 0) break; - Fraction percent = (tsAlignment->GetTime() - startTime) / duration; - tsAlignment->SetXRel(startXRel + space * percent.ToDouble()); + double percent = ((tsAlignment->GetTime() - startTime) / duration).ToDouble(); + tsAlignment->SetXRel(startXRel + space * percent); } m_timestamps.clear(); } From 978f146bcbb274acfc642664d9e60bcfca2bfee6 Mon Sep 17 00:00:00 2001 From: Laurent Pugin Date: Fri, 4 Oct 2024 15:17:02 +0200 Subject: [PATCH 18/25] Use Fraction for score time information --- include/vrv/beatrpt.h | 6 +- include/vrv/durationinterface.h | 20 +++--- include/vrv/measure.h | 6 +- include/vrv/midifunctor.h | 6 +- include/vrv/vrvdef.h | 10 +++ src/beatrpt.cpp | 6 +- src/durationinterface.cpp | 20 +++--- src/featureextractor.cpp | 2 +- src/iomusxml.cpp | 8 +-- src/measure.cpp | 4 +- src/midifunctor.cpp | 117 ++++++++++++++++---------------- 11 files changed, 106 insertions(+), 99 deletions(-) diff --git a/include/vrv/beatrpt.h b/include/vrv/beatrpt.h index bf892e589c0..5108e3bc67c 100644 --- a/include/vrv/beatrpt.h +++ b/include/vrv/beatrpt.h @@ -49,8 +49,8 @@ class BeatRpt : public LayerElement, public AttColor, public AttBeatRptLog, publ * MIDI timing information */ ///@{ - void SetScoreTimeOnset(double scoreTime); - double GetScoreTimeOnset() const; + void SetScoreTimeOnset(Fraction scoreTime); + Fraction GetScoreTimeOnset() const; //----------// // Functors // @@ -75,7 +75,7 @@ class BeatRpt : public LayerElement, public AttColor, public AttBeatRptLog, publ * The score-time onset of the note in the measure (duration from the start of measure in * quarter notes). */ - double m_scoreTimeOnset; + Fraction m_scoreTimeOnset; }; } // namespace vrv diff --git a/include/vrv/durationinterface.h b/include/vrv/durationinterface.h index 215ba4fce57..6a9c21292f9 100644 --- a/include/vrv/durationinterface.h +++ b/include/vrv/durationinterface.h @@ -114,17 +114,17 @@ class DurationInterface : public Interface, * MIDI timing information */ ///@{ - void SetScoreTimeOnset(double scoreTime); + void SetScoreTimeOnset(Fraction scoreTime); void SetRealTimeOnsetSeconds(double timeInSeconds); - void SetScoreTimeOffset(double scoreTime); + void SetScoreTimeOffset(Fraction scoreTime); void SetRealTimeOffsetSeconds(double timeInSeconds); - void SetScoreTimeTiedDuration(double timeInSeconds); - double GetScoreTimeOnset() const; + void SetScoreTimeTiedDuration(Fraction timeInSeconds); + Fraction GetScoreTimeOnset() const; double GetRealTimeOnsetMilliseconds() const; - double GetScoreTimeOffset() const; - double GetScoreTimeTiedDuration() const; + Fraction GetScoreTimeOffset() const; + Fraction GetScoreTimeTiedDuration() const; double GetRealTimeOffsetMilliseconds() const; - double GetScoreTimeDuration() const; + Fraction GetScoreTimeDuration() const; ///@} //-----------------// @@ -150,7 +150,7 @@ class DurationInterface : public Interface, * The score-time onset of the note in the measure (duration from the start of measure in * quarter notes). */ - double m_scoreTimeOnset; + Fraction m_scoreTimeOnset; /** * The score-time off-time of the note in the measure (duration from the start of the measure @@ -160,7 +160,7 @@ class DurationInterface : public Interface, * of the printed note, and the m_scoreTimeTiedDuration is -1.0 to indicate that it should not * be exported when creating a MIDI file. */ - double m_scoreTimeOffset; + Fraction m_scoreTimeOffset; /** * The time in milliseconds since the start of the measure element that contains the note. @@ -180,7 +180,7 @@ class DurationInterface : public Interface, * If the note is a secondary note in a tied group, then this variable is set to -1.0 to * indicate that it should not be written to MIDI output. */ - double m_scoreTimeTiedDuration; + Fraction m_scoreTimeTiedDuration; /** * The default duration: extracted from scoreDef/staffDef and used when no duration attribute is given diff --git a/include/vrv/measure.h b/include/vrv/measure.h index dcf96d15243..8069f161ae0 100644 --- a/include/vrv/measure.h +++ b/include/vrv/measure.h @@ -316,7 +316,7 @@ class Measure : public Object, /** * Read only access to m_scoreTimeOffset */ - double GetLastTimeOffset() const { return m_scoreTimeOffset.back(); } + Fraction GetLastTimeOffset() const { return m_scoreTimeOffset.back(); } /** * Return the real time offset in milliseconds @@ -331,7 +331,7 @@ class Measure : public Object, */ ///@{ void ClearScoreTimeOffset() { m_scoreTimeOffset.clear(); } - void AddScoreTimeOffset(double offset) { m_scoreTimeOffset.push_back(offset); } + void AddScoreTimeOffset(Fraction offset) { m_scoreTimeOffset.push_back(offset); } void ClearRealTimeOffset() { m_realTimeOffsetMilliseconds.clear(); } void AddRealTimeOffset(double milliseconds) { m_realTimeOffsetMilliseconds.push_back(milliseconds); } ///@} @@ -448,7 +448,7 @@ class Measure : public Object, /** * Start time state variables. */ - std::vector m_scoreTimeOffset; + std::vector m_scoreTimeOffset; std::vector m_realTimeOffsetMilliseconds; double m_currentTempo; diff --git a/include/vrv/midifunctor.h b/include/vrv/midifunctor.h index 8d7600bdf10..47e4b47d3bf 100644 --- a/include/vrv/midifunctor.h +++ b/include/vrv/midifunctor.h @@ -65,7 +65,7 @@ class InitOnsetOffsetFunctor : public Functor { // private: // The current score time in the measure (incremented by each element) - double m_currentScoreTime; + Fraction m_currentScoreTime; // The current real time in seconds in the measure (incremented by each element) double m_currentRealTimeSeconds; // The current time alignment parameters @@ -127,7 +127,7 @@ class InitMaxMeasureDurationFunctor : public Functor { // private: // The current score time - double m_currentScoreTime; + Fraction m_currentScoreTime; // The current time in seconds double m_currentRealTimeSeconds; // The current tempo @@ -423,7 +423,7 @@ class GenerateTimemapFunctor : public ConstFunctor { // private: // The score time from the start of the piece to the previous barline in quarter notes - double m_scoreTimeOffset; + Fraction m_scoreTimeOffset; // Real time from the start of the piece to the previous barline in ms double m_realTimeOffsetMilliseconds; // The current tempo diff --git a/include/vrv/vrvdef.h b/include/vrv/vrvdef.h index 66c40feceb4..5e02c4d153d 100644 --- a/include/vrv/vrvdef.h +++ b/include/vrv/vrvdef.h @@ -670,6 +670,16 @@ enum GraphicID { PRIMARY = 0, SPANNING, SYMBOLREF }; enum MeasureType { MEASURED = 0, UNMEASURED, NEUMELINE }; +//---------------------------------------------------------------------------- +// The score time unit (quarter note) +//---------------------------------------------------------------------------- + +#define SCORE_TIME_UNIT 4 + +//---------------------------------------------------------------------------- +// Section representing a line in neon +//---------------------------------------------------------------------------- + #define NEUME_LINE_TYPE "neon-neume-line" //---------------------------------------------------------------------------- diff --git a/src/beatrpt.cpp b/src/beatrpt.cpp index 26dc321bc07..d3221f02c46 100644 --- a/src/beatrpt.cpp +++ b/src/beatrpt.cpp @@ -51,7 +51,7 @@ void BeatRpt::Reset() this->ResetBeatRptVis(); this->ResetColor(); - m_scoreTimeOnset = 0.0; + m_scoreTimeOnset = 0; } Fraction BeatRpt::GetBeatRptAlignmentDuration(data_DURATION meterUnit) const @@ -61,12 +61,12 @@ Fraction BeatRpt::GetBeatRptAlignmentDuration(data_DURATION meterUnit) const return duration; } -void BeatRpt::SetScoreTimeOnset(double scoreTime) +void BeatRpt::SetScoreTimeOnset(Fraction scoreTime) { m_scoreTimeOnset = scoreTime; } -double BeatRpt::GetScoreTimeOnset() const +Fraction BeatRpt::GetScoreTimeOnset() const { return m_scoreTimeOnset; } diff --git a/src/durationinterface.cpp b/src/durationinterface.cpp index 68c05cea91e..71d7a8de98d 100644 --- a/src/durationinterface.cpp +++ b/src/durationinterface.cpp @@ -65,11 +65,11 @@ void DurationInterface::Reset() m_durDefault = DURATION_NONE; - m_scoreTimeOnset = 0.0; - m_scoreTimeOffset = 0.0; + m_scoreTimeOnset = 0; + m_scoreTimeOffset = 0; m_realTimeOnsetMilliseconds = 0; m_realTimeOffsetMilliseconds = 0; - m_scoreTimeTiedDuration = 0.0; + m_scoreTimeTiedDuration = 0; } Fraction DurationInterface::GetInterfaceAlignmentDuration(int num, int numBase) const @@ -251,7 +251,7 @@ bool DurationInterface::HasIdenticalDurationInterface(const DurationInterface *o */ } -void DurationInterface::SetScoreTimeOnset(double scoreTime) +void DurationInterface::SetScoreTimeOnset(Fraction scoreTime) { m_scoreTimeOnset = scoreTime; } @@ -262,7 +262,7 @@ void DurationInterface::SetRealTimeOnsetSeconds(double timeInSeconds) m_realTimeOnsetMilliseconds = timeInSeconds * 1000.0; } -void DurationInterface::SetScoreTimeOffset(double scoreTime) +void DurationInterface::SetScoreTimeOffset(Fraction scoreTime) { m_scoreTimeOffset = scoreTime; } @@ -273,12 +273,12 @@ void DurationInterface::SetRealTimeOffsetSeconds(double timeInSeconds) m_realTimeOffsetMilliseconds = timeInSeconds * 1000.0; } -void DurationInterface::SetScoreTimeTiedDuration(double scoreTime) +void DurationInterface::SetScoreTimeTiedDuration(Fraction scoreTime) { m_scoreTimeTiedDuration = scoreTime; } -double DurationInterface::GetScoreTimeOnset() const +Fraction DurationInterface::GetScoreTimeOnset() const { return m_scoreTimeOnset; } @@ -288,7 +288,7 @@ double DurationInterface::GetRealTimeOnsetMilliseconds() const return m_realTimeOnsetMilliseconds; } -double DurationInterface::GetScoreTimeOffset() const +Fraction DurationInterface::GetScoreTimeOffset() const { return m_scoreTimeOffset; } @@ -298,12 +298,12 @@ double DurationInterface::GetRealTimeOffsetMilliseconds() const return m_realTimeOffsetMilliseconds; } -double DurationInterface::GetScoreTimeTiedDuration() const +Fraction DurationInterface::GetScoreTimeTiedDuration() const { return m_scoreTimeTiedDuration; } -double DurationInterface::GetScoreTimeDuration() const +Fraction DurationInterface::GetScoreTimeDuration() const { return this->GetScoreTimeOffset() - this->GetScoreTimeOnset(); } diff --git a/src/featureextractor.cpp b/src/featureextractor.cpp index fad1e07b47b..a1c2a9e9a40 100644 --- a/src/featureextractor.cpp +++ b/src/featureextractor.cpp @@ -59,7 +59,7 @@ void FeatureExtractor::Extract(const Object *object) if (chord && (note != chord->GetTopNote())) return; // Check if the note is tied to a previous one and skip it if yes - if (note->GetScoreTimeTiedDuration() == -1.0) { + if (note->GetScoreTimeTiedDuration() == -1) { // Check if we need to add it to the previous interval ids const int intervalsIdsSize = (int)m_intervalsIds.size(); if (intervalsIdsSize > 0) m_intervalsIds.get(intervalsIdsSize - 1) << note->GetID(); diff --git a/src/iomusxml.cpp b/src/iomusxml.cpp index 0432bf0caf1..98a09782a54 100644 --- a/src/iomusxml.cpp +++ b/src/iomusxml.cpp @@ -1761,11 +1761,11 @@ void MusicXmlInput::MatchTies(bool matchLayers) // match tie stop with pitch/oct identity, with start note earlier than end note, // and with earliest end note. if ((iter->m_note->IsEnharmonicWith(jter->m_note)) - && (iter->m_note->GetScoreTimeOnset() < jter->m_note->GetScoreTimeOnset()) - && (jter->m_note->GetScoreTimeOnset() < lastScoreTimeOnset) + && (iter->m_note->GetRealTimeOnsetMilliseconds() < jter->m_note->GetRealTimeOnsetMilliseconds()) + && (jter->m_note->GetRealTimeOnsetMilliseconds() < lastScoreTimeOnset) && (!matchLayers || (iter->m_layerNum == jter->m_layerNum))) { iter->m_tie->SetEndid("#" + jter->m_note->GetID()); - lastScoreTimeOnset = jter->m_note->GetScoreTimeOnset(); + lastScoreTimeOnset = jter->m_note->GetRealTimeOnsetMilliseconds(); tieMatched = true; break; } @@ -2830,7 +2830,7 @@ void MusicXmlInput::ReadMusicXmlNote( if (!noteID.empty()) { note->SetID(noteID); } - note->SetScoreTimeOnset(onset); // remember the MIDI onset within that measure + note->SetRealTimeOnsetSeconds(onset); // remember the MIDI onset within that measure // set @staff attribute, if existing and different from parent staff number if (noteStaffNum > 0 && noteStaffNum + staffOffset != staff->GetN()) note->SetStaff( diff --git a/src/measure.cpp b/src/measure.cpp index 48bd70e42af..ea7b78ae3fd 100644 --- a/src/measure.cpp +++ b/src/measure.cpp @@ -475,8 +475,8 @@ const Staff *Measure::GetBottomVisibleStaff() const int Measure::EnclosesTime(int time) const { int repeat = 1; - double timeDuration = m_measureAligner.GetRightAlignment()->GetTime().ToDouble() * static_cast(DURATION_4) - / DUR_MAX * 60.0 / m_currentTempo * 1000.0 + double timeDuration + = m_measureAligner.GetRightAlignment()->GetTime().ToDouble() * SCORE_TIME_UNIT * 60.0 / m_currentTempo * 1000.0 + 0.5; std::vector::const_iterator iter; for (iter = m_realTimeOffsetMilliseconds.begin(); iter != m_realTimeOffsetMilliseconds.end(); ++iter) { diff --git a/src/midifunctor.cpp b/src/midifunctor.cpp index 45ea551835c..c05965ae93a 100644 --- a/src/midifunctor.cpp +++ b/src/midifunctor.cpp @@ -42,7 +42,7 @@ namespace vrv { InitOnsetOffsetFunctor::InitOnsetOffsetFunctor() : Functor() { - m_currentScoreTime = 0.0; + m_currentScoreTime = 0; m_currentRealTimeSeconds = 0.0; m_meterParams.mensur = NULL; m_meterParams.meterSig = NULL; @@ -54,11 +54,10 @@ FunctorCode InitOnsetOffsetFunctor::VisitChordEnd(Chord *chord) { LayerElement *element = chord->ThisOrSameasLink(); - double incrementScoreTime = element->GetAlignmentDuration(m_meterParams, true, m_notationType).ToDouble(); - incrementScoreTime = incrementScoreTime / (DUR_MAX / DURATION_4); - double realTimeIncrementSeconds = incrementScoreTime * 60.0 / m_currentTempo; + Fraction incrementScoreTime = element->GetAlignmentDuration(m_meterParams, true, m_notationType) * SCORE_TIME_UNIT; + double realTimeIncrementSeconds = incrementScoreTime.ToDouble() * 60.0 / m_currentTempo; - m_currentScoreTime += incrementScoreTime; + m_currentScoreTime = m_currentScoreTime + incrementScoreTime; m_currentRealTimeSeconds += realTimeIncrementSeconds; return FUNCTOR_CONTINUE; @@ -66,7 +65,7 @@ FunctorCode InitOnsetOffsetFunctor::VisitChordEnd(Chord *chord) FunctorCode InitOnsetOffsetFunctor::VisitLayer(Layer *layer) { - m_currentScoreTime = 0.0; + m_currentScoreTime = 0; m_currentRealTimeSeconds = 0.0; m_meterParams.mensur = layer->GetCurrentMensur(); @@ -81,22 +80,21 @@ FunctorCode InitOnsetOffsetFunctor::VisitLayerElement(LayerElement *layerElement LayerElement *element = layerElement->ThisOrSameasLink(); - double incrementScoreTime; + Fraction incrementScoreTime; if (element->Is(REST) || element->Is(SPACE)) { - incrementScoreTime = element->GetAlignmentDuration(m_meterParams, true, m_notationType).ToDouble(); - incrementScoreTime = incrementScoreTime / (DUR_MAX / DURATION_4); + incrementScoreTime = element->GetAlignmentDuration(m_meterParams, true, m_notationType) * SCORE_TIME_UNIT; // For rests to be possibly added to the timemap if (element->Is(REST)) { Rest *rest = vrv_cast(element); - double realTimeIncrementSeconds = incrementScoreTime * 60.0 / m_currentTempo; + double realTimeIncrementSeconds = incrementScoreTime.ToDouble() * 60.0 / m_currentTempo; rest->SetScoreTimeOnset(m_currentScoreTime); rest->SetRealTimeOnsetSeconds(m_currentRealTimeSeconds); rest->SetScoreTimeOffset(m_currentScoreTime + incrementScoreTime); rest->SetRealTimeOffsetSeconds(m_currentRealTimeSeconds + realTimeIncrementSeconds); } - m_currentScoreTime += incrementScoreTime; - m_currentRealTimeSeconds += incrementScoreTime * 60.0 / m_currentTempo; + m_currentScoreTime = m_currentScoreTime + incrementScoreTime; + m_currentRealTimeSeconds += incrementScoreTime.ToDouble() * 60.0 / m_currentTempo; } else if (element->Is(NOTE)) { Note *note = vrv_cast(element); @@ -111,16 +109,15 @@ FunctorCode InitOnsetOffsetFunctor::VisitLayerElement(LayerElement *layerElement // If the note has a @dur or a @dur.ges, take it into account // This means that overwriting only @dots or @dots.ges will not be taken into account if (chord && !note->HasDur() && !note->HasDurGes()) { - incrementScoreTime = chord->GetAlignmentDuration(m_meterParams, true, m_notationType).ToDouble(); + incrementScoreTime = chord->GetAlignmentDuration(m_meterParams, true, m_notationType) * SCORE_TIME_UNIT; } else if (tabGrp && !note->HasDur() && !note->HasDurGes()) { - incrementScoreTime = tabGrp->GetAlignmentDuration(m_meterParams, true, m_notationType).ToDouble(); + incrementScoreTime = tabGrp->GetAlignmentDuration(m_meterParams, true, m_notationType) * SCORE_TIME_UNIT; } else { - incrementScoreTime = note->GetAlignmentDuration(m_meterParams, true, m_notationType).ToDouble(); + incrementScoreTime = note->GetAlignmentDuration(m_meterParams, true, m_notationType) * SCORE_TIME_UNIT; } - incrementScoreTime = incrementScoreTime / (DUR_MAX / DURATION_4); - double realTimeIncrementSeconds = incrementScoreTime * 60.0 / m_currentTempo; + double realTimeIncrementSeconds = incrementScoreTime.ToDouble() * 60.0 / m_currentTempo; // LogDebug("Note Alignment Duration %f - Dur %d - Diatonic Pitch %d - Track %d", GetAlignmentDuration(), // note->GetNoteOrChordDur(element), note->GetDiatonicPitch(), *midiTrack); @@ -137,7 +134,7 @@ FunctorCode InitOnsetOffsetFunctor::VisitLayerElement(LayerElement *layerElement // increase the currentTime accordingly, but only if not in a chord or tabGrp if (!note->IsChordTone() && !note->IsTabGrpNote()) { - m_currentScoreTime += incrementScoreTime; + m_currentScoreTime = m_currentScoreTime + incrementScoreTime; m_currentRealTimeSeconds += realTimeIncrementSeconds; } } @@ -145,18 +142,16 @@ FunctorCode InitOnsetOffsetFunctor::VisitLayerElement(LayerElement *layerElement BeatRpt *rpt = vrv_cast(element); assert(rpt); - incrementScoreTime = rpt->GetAlignmentDuration(m_meterParams, true, m_notationType).ToDouble(); - incrementScoreTime = incrementScoreTime / (DUR_MAX / DURATION_4); + incrementScoreTime = rpt->GetAlignmentDuration(m_meterParams, true, m_notationType) * SCORE_TIME_UNIT; rpt->SetScoreTimeOnset(m_currentScoreTime); - m_currentScoreTime += incrementScoreTime; - m_currentRealTimeSeconds += incrementScoreTime * 60.0 / m_currentTempo; + m_currentScoreTime = m_currentScoreTime + incrementScoreTime; + m_currentRealTimeSeconds += incrementScoreTime.ToDouble() * 60.0 / m_currentTempo; } else if (layerElement->Is({ BEAM, LIGATURE, FTREM, TUPLET }) && layerElement->HasSameasLink()) { incrementScoreTime - = layerElement->GetSameAsContentAlignmentDuration(m_meterParams, true, m_notationType).ToDouble(); - incrementScoreTime = incrementScoreTime / (DUR_MAX / DURATION_4); - m_currentScoreTime += incrementScoreTime; - m_currentRealTimeSeconds += incrementScoreTime * 60.0 / m_currentTempo; + = layerElement->GetSameAsContentAlignmentDuration(m_meterParams, true, m_notationType) * SCORE_TIME_UNIT; + m_currentScoreTime = m_currentScoreTime + incrementScoreTime; + m_currentRealTimeSeconds += incrementScoreTime.ToDouble() * 60.0 / m_currentTempo; } else if (layerElement->Is(MENSUR)) { this->m_meterParams.mensur = vrv_cast(layerElement); @@ -189,11 +184,10 @@ FunctorCode InitOnsetOffsetFunctor::VisitTabGrpEnd(TabGrp *tabGrp) { LayerElement *element = tabGrp->ThisOrSameasLink(); - double incrementScoreTime = element->GetAlignmentDuration(m_meterParams, true, m_notationType).ToDouble(); - incrementScoreTime = incrementScoreTime / (DUR_MAX / DURATION_4); - double realTimeIncrementSeconds = incrementScoreTime * 60.0 / m_currentTempo; + Fraction incrementScoreTime = element->GetAlignmentDuration(m_meterParams, true, m_notationType) * SCORE_TIME_UNIT; + double realTimeIncrementSeconds = incrementScoreTime.ToDouble() * 60.0 / m_currentTempo; - m_currentScoreTime += incrementScoreTime; + m_currentScoreTime = m_currentScoreTime + incrementScoreTime; m_currentRealTimeSeconds += realTimeIncrementSeconds; return FUNCTOR_CONTINUE; @@ -205,7 +199,7 @@ FunctorCode InitOnsetOffsetFunctor::VisitTabGrpEnd(TabGrp *tabGrp) InitMaxMeasureDurationFunctor::InitMaxMeasureDurationFunctor() : Functor() { - m_currentScoreTime = 0.0; + m_currentScoreTime = 0; m_currentRealTimeSeconds = 0.0; m_currentTempo = MIDI_TEMPO; m_tempoAdjustment = 1.0; @@ -239,10 +233,10 @@ FunctorCode InitMaxMeasureDurationFunctor::VisitMeasureEnd(Measure *measure) const double tempo = this->GetAdjustedTempo(); measure->SetCurrentTempo(tempo); - const double scoreTimeIncrement = measure->m_measureAligner.GetRightAlignment()->GetTime().ToDouble() - * m_multiRestFactor * static_cast(DURATION_4) / DUR_MAX; - m_currentScoreTime += scoreTimeIncrement; - m_currentRealTimeSeconds += scoreTimeIncrement * 60.0 / tempo; + const Fraction scoreTimeIncrement + = measure->m_measureAligner.GetRightAlignment()->GetTime() * m_multiRestFactor * SCORE_TIME_UNIT; + m_currentScoreTime = m_currentScoreTime + scoreTimeIncrement; + m_currentRealTimeSeconds += scoreTimeIncrement.ToDouble() * 60.0 / tempo; m_multiRestFactor = 1; return FUNCTOR_CONTINUE; @@ -287,16 +281,16 @@ FunctorCode InitTimemapTiesFunctor::VisitTie(Tie *tie) return FUNCTOR_CONTINUE; } - double sttd2 = note2->GetScoreTimeTiedDuration(); - double std2 = note2->GetScoreTimeDuration(); + Fraction sttd2 = note2->GetScoreTimeTiedDuration(); + Fraction std2 = note2->GetScoreTimeDuration(); - if (sttd2 > 0.0) { + if (sttd2 > 0) { note1->SetScoreTimeTiedDuration(sttd2 + std2); } else { note1->SetScoreTimeTiedDuration(std2); } - note2->SetScoreTimeTiedDuration(-1.0); + note2->SetScoreTimeTiedDuration(-1); return FUNCTOR_SIBLINGS; } @@ -363,8 +357,8 @@ FunctorCode GenerateMIDIFunctor::VisitBeatRpt(const BeatRpt *beatRpt) { // Sameas not taken into account for now AlignMeterParams params; - double beatLength = beatRpt->GetAlignmentDuration(params).ToDouble() / (DUR_MAX / DURATION_4); - double startTime = m_totalTime + beatRpt->GetScoreTimeOnset(); + double beatLength = beatRpt->GetAlignmentDuration(params).ToDouble() * SCORE_TIME_UNIT; + double startTime = m_totalTime + beatRpt->GetScoreTimeOnset().ToDouble(); int tpq = m_midiFile->getTPQ(); // filter last beat and copy all notes @@ -418,7 +412,8 @@ FunctorCode GenerateMIDIFunctor::VisitBTrem(const BTrem *bTrem) const Note *note = vrv_cast(obj); assert(note); const int pitch = note->GetMIDIPitch(m_transSemi); - const double totalInQuarterDur = note->GetScoreTimeDuration() + note->GetScoreTimeTiedDuration(); + const double totalInQuarterDur + = note->GetScoreTimeDuration().ToDouble() + note->GetScoreTimeTiedDuration().ToDouble(); int multiplicity = totalInQuarterDur / noteInQuarterDur; double noteDuration = noteInQuarterDur; // if NUM has been set for the bTrem, override calculated values @@ -490,7 +485,7 @@ FunctorCode GenerateMIDIFunctor::VisitGraceGrpEnd(const GraceGrp *graceGrp) // Handling of Nachschlag if (!m_graceNotes.empty() && (graceGrp->GetAttach() == graceGrpLog_ATTACH_pre) && !m_accentedGraceNote && m_lastNote) { - double startTime = m_totalTime + m_lastNote->GetScoreTimeOffset(); + double startTime = m_totalTime + m_lastNote->GetScoreTimeOffset().ToDouble(); const double graceNoteDur = UNACC_GRACENOTE_DUR * m_currentTempo / 60000.0; const double totalDur = graceNoteDur * m_graceNotes.size(); startTime -= totalDur; @@ -559,7 +554,7 @@ FunctorCode GenerateMIDIFunctor::VisitLayerElement(const LayerElement *layerElem FunctorCode GenerateMIDIFunctor::VisitMeasure(const Measure *measure) { // Here we need to update the m_totalTime from the starting time of the measure. - m_totalTime = measure->GetLastTimeOffset(); + m_totalTime = measure->GetLastTimeOffset().ToDouble(); if (measure->GetCurrentTempo() != m_currentTempo) { m_currentTempo = measure->GetCurrentTempo(); @@ -593,7 +588,7 @@ FunctorCode GenerateMIDIFunctor::VisitNote(const Note *note) } // If the note is a secondary tied note, then ignore it - if (note->GetScoreTimeTiedDuration() < 0.0) { + if (note->GetScoreTimeTiedDuration() < 0) { return FUNCTOR_SIBLINGS; } @@ -621,7 +616,7 @@ FunctorCode GenerateMIDIFunctor::VisitNote(const Note *note) int velocity = MIDI_VELOCITY; if (note->HasVel()) velocity = note->GetVel(); - double startTime = m_totalTime + note->GetScoreTimeOnset(); + double startTime = m_totalTime + note->GetScoreTimeOnset().ToDouble(); const int tpq = m_midiFile->getTPQ(); // Check if some grace notes must be performed @@ -680,13 +675,15 @@ FunctorCode GenerateMIDIFunctor::VisitNote(const Note *note) const double defaultHoldTime = 4; // quarter notes m_heldNotes[course - 1].m_pitch = pitch; m_heldNotes[course - 1].m_stopTime = m_totalTime - + std::max(defaultHoldTime, note->GetScoreTimeOffset() + note->GetScoreTimeTiedDuration()); + + std::max(defaultHoldTime, + note->GetScoreTimeOffset().ToDouble() + note->GetScoreTimeTiedDuration().ToDouble()); // start this note m_midiFile->addNoteOn(m_midiTrack, startTime * tpq, channel, pitch, velocity); } else { - const double stopTime = m_totalTime + note->GetScoreTimeOffset() + note->GetScoreTimeTiedDuration(); + const double stopTime + = m_totalTime + note->GetScoreTimeOffset().ToDouble() + note->GetScoreTimeTiedDuration().ToDouble(); m_midiFile->addNoteOn(m_midiTrack, startTime * tpq, channel, pitch, velocity); m_midiFile->addNoteOff(m_midiTrack, stopTime * tpq, channel, pitch); @@ -703,7 +700,7 @@ FunctorCode GenerateMIDIFunctor::VisitPedal(const Pedal *pedal) { if (!pedal->HasDir()) return FUNCTOR_CONTINUE; - double pedalTime = pedal->GetStart()->GetAlignment()->GetTime().ToDouble() * static_cast(DURATION_4) / DUR_MAX; + double pedalTime = pedal->GetStart()->GetAlignment()->GetTime().ToDouble() * SCORE_TIME_UNIT; double startTime = m_totalTime + pedalTime; int tpq = m_midiFile->getTPQ(); @@ -730,7 +727,7 @@ FunctorCode GenerateMIDIFunctor::VisitScoreDef(const ScoreDef *scoreDef) const Object *next = parent->GetNext(scoreDef); if (next && next->Is(MEASURE)) { const Measure *nextMeasure = vrv_cast(next); - totalTime = nextMeasure->GetLastTimeOffset(); + totalTime = nextMeasure->GetLastTimeOffset().ToDouble(); } } const double currentTick = totalTime * m_midiFile->getTPQ(); @@ -803,7 +800,7 @@ FunctorCode GenerateMIDIFunctor::VisitStaffDef(const StaffDef *staffDef) FunctorCode GenerateMIDIFunctor::VisitSyl(const Syl *syl) { - const double startTime = m_totalTime + m_lastNote->GetScoreTimeOnset(); + const double startTime = m_totalTime + m_lastNote->GetScoreTimeOnset().ToDouble(); const std::string sylText = UTF32to8(syl->GetText()); m_midiFile->addLyric(m_midiTrack, startTime * m_midiFile->getTPQ(), sylText); @@ -840,7 +837,7 @@ void GenerateMIDIFunctor::DeferMIDINote(const Note *refNote, double shift, bool } // Register the shift - if (shift < refNote->GetScoreTimeDuration() + refNote->GetScoreTimeTiedDuration()) { + if (shift < refNote->GetScoreTimeDuration().ToDouble() + refNote->GetScoreTimeTiedDuration().ToDouble()) { m_deferredNotes[refNote] = shift; } } @@ -850,7 +847,7 @@ void GenerateMIDIFunctor::GenerateGraceNoteMIDI( { double graceNoteDur = 0.0; if (m_accentedGraceNote && !m_graceNotes.empty()) { - const double totalDur = refNote->GetScoreTimeDuration() / 2.0; + const double totalDur = refNote->GetScoreTimeDuration().ToDouble() / 2.0; this->DeferMIDINote(refNote, totalDur, true); graceNoteDur = totalDur / m_graceNotes.size(); } @@ -881,7 +878,7 @@ void GenerateMIDIFunctor::GenerateGraceNoteMIDI( GenerateTimemapFunctor::GenerateTimemapFunctor(Timemap *timemap) : ConstFunctor() { - m_scoreTimeOffset = 0.0; + m_scoreTimeOffset = 0; m_realTimeOffsetMilliseconds = 0.0; m_currentTempo = MIDI_TEMPO; m_cueExclusion = false; @@ -945,10 +942,10 @@ void GenerateTimemapFunctor::AddTimemapEntry(const Object *object) assert(interface); double realTimeStart = round(m_realTimeOffsetMilliseconds + interface->GetRealTimeOnsetMilliseconds()); - double scoreTimeStart = m_scoreTimeOffset + interface->GetScoreTimeOnset(); + Fraction scoreTimeStart = m_scoreTimeOffset + interface->GetScoreTimeOnset(); double realTimeEnd = round(m_realTimeOffsetMilliseconds + interface->GetRealTimeOffsetMilliseconds()); - double scoreTimeEnd = m_scoreTimeOffset + interface->GetScoreTimeOffset(); + Fraction scoreTimeEnd = m_scoreTimeOffset + interface->GetScoreTimeOffset(); bool isRest = (object->Is(REST)); @@ -958,7 +955,7 @@ void GenerateTimemapFunctor::AddTimemapEntry(const Object *object) // Should check if value for realTimeStart already exists and if so, then // ensure that it is equal to scoreTimeStart: - startEntry.qstamp = scoreTimeStart; + startEntry.qstamp = scoreTimeStart.ToDouble(); // Store the element ID in list to turn on at given time - note or rest if (!isRest) startEntry.notesOn.push_back(object->GetID()); @@ -973,7 +970,7 @@ void GenerateTimemapFunctor::AddTimemapEntry(const Object *object) // Should check if value for realTimeEnd already exists and if so, then // ensure that it is equal to scoreTimeEnd: - endEntry.qstamp = scoreTimeEnd; + endEntry.qstamp = scoreTimeEnd.ToDouble(); // Store the element ID in list to turn off at given time - notes or rest if (!isRest) endEntry.notesOff.push_back(object->GetID()); @@ -985,14 +982,14 @@ void GenerateTimemapFunctor::AddTimemapEntry(const Object *object) assert(measure); // Deal with repeated music later, for now get the last times. - double scoreTimeStart = m_scoreTimeOffset; + Fraction scoreTimeStart = m_scoreTimeOffset; double realTimeStart = round(m_realTimeOffsetMilliseconds); TimemapEntry &startEntry = m_timemap->GetEntry(realTimeStart); // Should check if value for realTimeStart already exists and if so, then // ensure that it is equal to scoreTimeStart: - startEntry.qstamp = scoreTimeStart; + startEntry.qstamp = scoreTimeStart.ToDouble(); // Add the measureOn startEntry.measureOn = measure->GetID(); From 20cfa2b6c0e47bb7f0a4d7229d6610f0a1a02c22 Mon Sep 17 00:00:00 2001 From: Laurent Pugin Date: Fri, 4 Oct 2024 15:43:49 +0200 Subject: [PATCH 19/25] Add test to avoid useless division in Fraction::Reduce --- src/horizontalaligner.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/horizontalaligner.cpp b/src/horizontalaligner.cpp index f1a68746279..6b6098f28eb 100644 --- a/src/horizontalaligner.cpp +++ b/src/horizontalaligner.cpp @@ -131,8 +131,10 @@ void Fraction::Reduce() m_denominator = -m_denominator; } int gcdVal = std::gcd(abs(m_numerator), abs(m_denominator)); - m_numerator /= gcdVal; - m_denominator /= gcdVal; + if (gcdVal != 1) { + m_numerator /= gcdVal; + m_denominator /= gcdVal; + } } std::pair Fraction::ToDur() const From bb9a38cab0308569885d16402f044e2a06e1c359 Mon Sep 17 00:00:00 2001 From: Laurent Pugin Date: Sat, 5 Oct 2024 14:35:05 +0200 Subject: [PATCH 20/25] Use Fraction in mensural alignment --- src/durationinterface.cpp | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/src/durationinterface.cpp b/src/durationinterface.cpp index 71d7a8de98d..075c3ab2dd5 100644 --- a/src/durationinterface.cpp +++ b/src/durationinterface.cpp @@ -82,8 +82,6 @@ Fraction DurationInterface::GetInterfaceAlignmentDuration(int num, int numBase) Fraction duration(noteDur); duration = duration * numBase / num; - // double old = DUR_MAX / pow(2.0, (double)(noteDur - 2.0)) * numBase / num; - // duration = DUR_MAX / pow(2.0, (double)(noteDur - 2.0)) * numBase / num; int noteDots = (this->HasDotsGes()) ? this->GetDotsGes() : this->GetDots(); if (noteDots != VRV_UNSET) { @@ -97,7 +95,7 @@ Fraction DurationInterface::GetInterfaceAlignmentDuration(int num, int numBase) Fraction DurationInterface::GetInterfaceAlignmentMensuralDuration( int num, int numBase, const Mensur *currentMensur) const { - int noteDur = this->GetDurGes() != DURATION_NONE ? this->GetActualDurGes() : this->GetActualDur(); + data_DURATION noteDur = this->GetDurGes() != DURATION_NONE ? this->GetActualDurGes() : this->GetActualDur(); if (noteDur == DURATION_NONE) noteDur = DURATION_4; if (!currentMensur) { @@ -141,24 +139,24 @@ Fraction DurationInterface::GetInterfaceAlignmentMensuralDuration( if (currentMensur->HasNum()) num *= currentMensur->GetNum(); if (currentMensur->HasNumbase()) numBase *= currentMensur->GetNumbase(); - double ratio = 0.0; - double duration = (double)DUR_MENSURAL_REF; + int ratio = 0; + Fraction duration(DURATION_breve); switch (noteDur) { case DURATION_maxima: - duration *= (double)abs(currentMensur->GetModusminor()) * (double)abs(currentMensur->GetModusmaior()); + duration = duration * abs(currentMensur->GetModusminor()) * abs(currentMensur->GetModusmaior()); break; - case DURATION_long: duration *= (double)abs(currentMensur->GetModusminor()); break; + case DURATION_long: duration = duration * abs(currentMensur->GetModusminor()); break; case DURATION_breve: break; - case DURATION_1: duration /= (double)abs(currentMensur->GetTempus()); break; + case DURATION_1: duration = duration / abs(currentMensur->GetTempus()); break; default: ratio = pow(2.0, (double)(noteDur - DURATION_2)); - duration /= (double)abs(currentMensur->GetTempus()) * (double)abs(currentMensur->GetProlatio()) * ratio; + assert(ratio); + duration = duration / abs(currentMensur->GetTempus()) / abs(currentMensur->GetProlatio()) / ratio; break; } - duration *= (double)numBase / (double)num; - // LogDebug("Duration %d; %d/%d; Alignment %f; Ratio %f", noteDur, num, numbase, duration, ratio); - duration = durRound(duration); - return Fraction(DUR_MAX * duration, DUR_MAX * DUR_MAX); + duration = duration * numBase / num; + + return duration; } bool DurationInterface::IsFirstInBeam(const LayerElement *noteOrRest) const @@ -193,9 +191,9 @@ data_DURATION DurationInterface::GetActualDurGes() const data_DURATION DurationInterface::CalcActualDur(data_DURATION dur) const { - // maxima (-1) is a mensural only value - if (dur < DUR_MAX) return dur; - // Mensural duration (except maxima) + // No mapping needed for values below, including maxima and NONE + if (dur < DURATION_longa) return dur; + // Mensural durations (except maxima) switch (dur) { case DURATION_longa: return DURATION_long; case DURATION_brevis: return DURATION_breve; @@ -235,7 +233,7 @@ bool DurationInterface::IsMensuralDur() const { // maxima (-1) is a mensural only value if (this->GetDur() == DURATION_maxima) return true; - return (this->GetDur() > DUR_MENSURAL_MASK); + return (this->GetDur() >= DURATION_longa); } bool DurationInterface::HasIdenticalDurationInterface(const DurationInterface *otherDurationInterface) const From 0acd8346a841ba61c91b3e044c602534d7850bde Mon Sep 17 00:00:00 2001 From: Laurent Pugin Date: Sat, 5 Oct 2024 14:36:00 +0200 Subject: [PATCH 21/25] Additional cleanup * Remove some duration defines * Remove some uses of DUR_MAX * Adjust code comments --- include/vrv/durationinterface.h | 5 ++--- include/vrv/horizontalaligner.h | 2 +- include/vrv/vrvdef.h | 2 -- libmei/addons/attdef.h | 11 +++-------- src/drawinginterface.cpp | 2 +- src/horizontalaligner.cpp | 1 - src/layer.cpp | 1 - src/view_element.cpp | 2 +- 8 files changed, 8 insertions(+), 18 deletions(-) diff --git a/include/vrv/durationinterface.h b/include/vrv/durationinterface.h index 6a9c21292f9..2a101f46e8c 100644 --- a/include/vrv/durationinterface.h +++ b/include/vrv/durationinterface.h @@ -67,7 +67,7 @@ class DurationInterface : public Interface, /** * Returns the duration (in Fraction) for the element for mensural notation - * Currently this assume brevis equality (through DUR_MENSURAL_REF) and would + * Currently this assume brevis equality and would * need to be modified for shorter equality in later repertoire. */ Fraction GetInterfaceAlignmentMensuralDuration(int num, int numBase, const Mensur *currentMensur) const; @@ -85,8 +85,7 @@ class DurationInterface : public Interface, /** * @name Return the actual (gestural) duration of the note, for both CMN and mensural durations * See data_DURATION - * For CMN, it is the same (DURATION_1 == DURATION_1) - * For mensural, we need to apply the DUR_MENSURAL_MASK + * For Mensural, it is the same (DURATION_2 == DURATION_minima) */ ///@{ data_DURATION GetActualDur() const; diff --git a/include/vrv/horizontalaligner.h b/include/vrv/horizontalaligner.h index 25ca888dbb3..fa761c6e549 100644 --- a/include/vrv/horizontalaligner.h +++ b/include/vrv/horizontalaligner.h @@ -527,7 +527,7 @@ class MeasureAligner : public HorizontalAligner { /** * Get left Alignment for the measure and for the left BarLine. * For each MeasureAligner, we keep and Alignment for the left position. - * The Alignment time will be always -1.0 * DUR_MAX and will appear first in the list. + * The Alignment time will be always -1.0 and will appear first in the list. */ ///@{ Alignment *GetLeftAlignment() { return m_leftAlignment; } diff --git a/include/vrv/vrvdef.h b/include/vrv/vrvdef.h index 5e02c4d153d..b596eac7762 100644 --- a/include/vrv/vrvdef.h +++ b/include/vrv/vrvdef.h @@ -430,8 +430,6 @@ typedef std::map StaffN_LayerN_VerseN_t; #define isIn(x, a, b) (((x) >= std::min((a), (b))) && ((x) <= std::max((a), (b)))) -#define durRound(dur) round(dur *pow(10, 8)) / pow(10, 8) - /** * Codes returned by Functors. * Default is FUNCTOR_CONTINUE. diff --git a/libmei/addons/attdef.h b/libmei/addons/attdef.h index 1bbd8de2975..04ee0b3c3ed 100644 --- a/libmei/addons/attdef.h +++ b/libmei/addons/attdef.h @@ -34,12 +34,7 @@ typedef double data_VU; //---------------------------------------------------------------------------- // used for alignement -#define DUR_MAX 1024 -// mensural duration -#define DUR_MENSURAL_OFFSET (2 * DUR_MAX) -#define DUR_MENSURAL_MASK (2 * DUR_MAX - 1) -// used for mensural alignment -#define DUR_MENSURAL_REF 1728 +#define DUR_MAX 2048 //---------------------------------------------------------------------------- // MEI data defines @@ -98,8 +93,8 @@ enum data_DURATION { DURATION_512, DURATION_1024, // 12 DURATION_2048, - DURATION_longa = DUR_MENSURAL_OFFSET + DURATION_long, - DURATION_brevis, + DURATION_longa = 100, + DURATION_brevis, // 101 DURATION_semibrevis, DURATION_minima, DURATION_semiminima, diff --git a/src/drawinginterface.cpp b/src/drawinginterface.cpp index c4a102a9432..09f209df455 100644 --- a/src/drawinginterface.cpp +++ b/src/drawinginterface.cpp @@ -420,7 +420,7 @@ bool BeamDrawingInterface::IsRepeatedPattern() const for (BeamElementCoord *coord : m_beamElementCoords) { if (!coord->m_stem || !coord->m_closestNote) continue; - // Could this be an overflow with 32 bits? + // Could this be an overflow with 32 bits? Not sure why DUR_MAX is used here items.push_back(coord->m_closestNote->GetDrawingY() + DUR_MAX * coord->m_dur); } int itemCount = (int)items.size(); diff --git a/src/horizontalaligner.cpp b/src/horizontalaligner.cpp index 6b6098f28eb..5e1a30ae9b8 100644 --- a/src/horizontalaligner.cpp +++ b/src/horizontalaligner.cpp @@ -272,7 +272,6 @@ bool MeasureAligner::IsSupportedChild(Object *child) Alignment *MeasureAligner::GetAlignmentAtTime(const Fraction &time, AlignmentType type) { int idx; // the index if we reach the end. - // time = durRound(time); Alignment *alignment = this->SearchAlignmentAtTime(time, type, idx); // we already have a alignment of the type at that time if (alignment != NULL) return alignment; diff --git a/src/layer.cpp b/src/layer.cpp index e76afa8c94d..eaa30b8be3d 100644 --- a/src/layer.cpp +++ b/src/layer.cpp @@ -362,7 +362,6 @@ data_STEMDIRECTION Layer::GetDrawingStemDir(const ArrayOfBeamElementCoords *coor else { duration = measure->m_measureAligner.GetRightAlignment()->GetTime() - time; } - // duration = durRound(duration); if (this->GetLayerCountInTimeSpan(time, duration, measure, staff->GetN()) < 2) { return STEMDIRECTION_NONE; diff --git a/src/view_element.cpp b/src/view_element.cpp index 9766eac5833..efa5fd74b63 100644 --- a/src/view_element.cpp +++ b/src/view_element.cpp @@ -1174,7 +1174,7 @@ void View::DrawMRest(DeviceContext *dc, LayerElement *element, Layer *layer, Sta this->DrawSmuflCode(dc, x, y, rest, staffSize, drawingCueSize); // single legder line for whole rest glyphs - if ((measure->m_measureAligner.GetMaxTime() < (DUR_MAX * 2)) + if ((measure->m_measureAligner.GetMaxTime() < Fraction(DURATION_1)) && (y > staff->GetDrawingY() || y < staff->GetDrawingY() - (staff->m_drawingLines - 1) * m_doc->GetDrawingDoubleUnit(staffSize))) { const int width = m_doc->GetGlyphWidth(rest, staffSize, drawingCueSize); From 3a7bcefad631b54fb56169dda681faf076ac26c2 Mon Sep 17 00:00:00 2001 From: Laurent Pugin Date: Sat, 5 Oct 2024 14:59:29 +0200 Subject: [PATCH 22/25] Add static function to reduce are fraction --- include/vrv/horizontalaligner.h | 7 +++++++ src/horizontalaligner.cpp | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/include/vrv/horizontalaligner.h b/include/vrv/horizontalaligner.h index fa761c6e549..d6d428ec211 100644 --- a/include/vrv/horizontalaligner.h +++ b/include/vrv/horizontalaligner.h @@ -110,6 +110,13 @@ class Fraction { /** Convert to data_DURATION and the remaining Fraction */ std::pair ToDur() const; + //----------------// + // Static methods // + //----------------// + + /** Reduce the faction represented by the two numbers */ + static void Reduce(int &numerator, int &denominator); + private: /** Reduce the fraction */ void Reduce(); diff --git a/src/horizontalaligner.cpp b/src/horizontalaligner.cpp index 5e1a30ae9b8..aa837ebd4d2 100644 --- a/src/horizontalaligner.cpp +++ b/src/horizontalaligner.cpp @@ -152,6 +152,13 @@ std::pair Fraction::ToDur() const return { dur, remainder }; } +void Fraction::Reduce(int &numerator, int &denominator) +{ + Fraction fraction(numerator, denominator); + numerator = fraction.GetNumerator(); + denominator = fraction.GetDenominator(); +} + //---------------------------------------------------------------------------- // HorizontalAligner //---------------------------------------------------------------------------- From ff7b7051f875ef9924bd4a48bce4a3d82eb0b6e5 Mon Sep 17 00:00:00 2001 From: Laurent Pugin Date: Sun, 6 Oct 2024 23:17:32 +0200 Subject: [PATCH 23/25] Adjust fraction constructor min / max --- src/horizontalaligner.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/horizontalaligner.cpp b/src/horizontalaligner.cpp index aa837ebd4d2..00da607789e 100644 --- a/src/horizontalaligner.cpp +++ b/src/horizontalaligner.cpp @@ -49,8 +49,8 @@ Fraction::Fraction(int num, int denom) : m_numerator(num), m_denominator(denom) Fraction::Fraction(data_DURATION duration) { - duration = vrv::DurationMin(duration, DURATION_1024); - duration = vrv::DurationMax(duration, DURATION_NONE); + duration = vrv::DurationMin(duration, DURATION_2048); + duration = vrv::DurationMax(duration, DURATION_maxima); int den = pow(2, (duration + 1)); m_numerator = 8; m_denominator = den; From 98c272adc98824db5c62852790d29a10d745ef35 Mon Sep 17 00:00:00 2001 From: Laurent Pugin Date: Sun, 6 Oct 2024 23:18:11 +0200 Subject: [PATCH 24/25] Fix Fraction == operator * Using the spaceship operator did not work - to be investigated --- src/horizontalaligner.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/horizontalaligner.cpp b/src/horizontalaligner.cpp index 00da607789e..ddbf4e04f93 100644 --- a/src/horizontalaligner.cpp +++ b/src/horizontalaligner.cpp @@ -91,7 +91,7 @@ Fraction Fraction::operator/(const Fraction &other) const bool Fraction::operator==(const Fraction &other) const { - return (m_numerator == other.m_numerator) && (m_denominator == other.m_denominator); + return m_numerator * other.m_denominator == other.m_numerator * m_denominator; } bool Fraction::operator<(const Fraction &other) const From 775021d5d1cb4c7c0dc899c0098b9ecd79633d2d Mon Sep 17 00:00:00 2001 From: Laurent Pugin Date: Mon, 7 Oct 2024 10:30:22 +0200 Subject: [PATCH 25/25] Prevent mis-calculation with tuplets without nun or numbase --- src/layerelement.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/layerelement.cpp b/src/layerelement.cpp index 20f59628df1..ceda043f433 100644 --- a/src/layerelement.cpp +++ b/src/layerelement.cpp @@ -693,9 +693,9 @@ Fraction LayerElement::GetAlignmentDuration( if (objects.size() > 0) { num = tuplet->GetNum(); numbase = tuplet->GetNumbase(); - // 0 is not valid in MEI anyway - just correct it silently - if (num == 0) num = 1; - if (numbase == 0) numbase = 1; + // Adjust VRV_UNSET and 0 - which is not valid in MEI anyway + num = std::max(1, num); + numbase = std::max(1, numbase); } } const DurationInterface *duration = this->GetDurationInterface();