Skip to content

Commit

Permalink
Change octave shift by comparing alignments
Browse files Browse the repository at this point in the history
  • Loading branch information
brdvd committed Dec 27, 2024
1 parent e2dbc00 commit 0d60320
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 34 deletions.
7 changes: 2 additions & 5 deletions include/vrv/midifunctor.h
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ struct OctaveInfo {
int staffN;
int layerN;
int octaveShift;
bool isActive;
};

/**
Expand Down Expand Up @@ -331,7 +332,6 @@ class GenerateMIDIFunctor : public ConstFunctor {
FunctorCode VisitLayer(const Layer *layer) override;
FunctorCode VisitLayerEnd(const Layer *layer) override;
FunctorCode VisitLayerElement(const LayerElement *layerElement) override;
FunctorCode VisitLayerElementEnd(const LayerElement *layerElement) override;
FunctorCode VisitMeasure(const Measure *measure) override;
FunctorCode VisitMRpt(const MRpt *mRpt) override;
FunctorCode VisitNote(const Note *note) override;
Expand Down Expand Up @@ -359,10 +359,7 @@ class GenerateMIDIFunctor : public ConstFunctor {
/**
* Change the octave shift at the begin/end of octaves
*/
///@{
void HandleOctaveBegin(const LayerElement *layerElement);
void HandleOctaveEnd(const LayerElement *layerElement);
///@}
void HandleOctave(const LayerElement *layerElement);

/**
* Convenience helper
Expand Down
62 changes: 33 additions & 29 deletions src/midifunctor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,7 @@ FunctorCode InitMIDIFunctor::VisitOctave(const Octave *octave)
const Layer *layer = vrv_cast<const Layer *>(raisePitch ? staff->GetFirst(LAYER) : staff->GetLast(LAYER));
assert(layer);

m_octaves.push_back({ octave, staff->GetN(), layer->GetN(), (raisePitch ? shift : -shift) });
m_octaves.push_back({ octave, staff->GetN(), layer->GetN(), (raisePitch ? shift : -shift), false });

return FUNCTOR_CONTINUE;
}
Expand Down Expand Up @@ -487,7 +487,7 @@ FunctorCode GenerateMIDIFunctor::VisitBTrem(const BTrem *bTrem)

FunctorCode GenerateMIDIFunctor::VisitChord(const Chord *chord)
{
this->HandleOctaveBegin(chord);
this->HandleOctave(chord);

// Handle grace chords
if (chord->IsGraceNote()) {
Expand Down Expand Up @@ -520,7 +520,7 @@ FunctorCode GenerateMIDIFunctor::VisitChord(const Chord *chord)

FunctorCode GenerateMIDIFunctor::VisitFTrem(const FTrem *fTrem)
{
this->HandleOctaveBegin(fTrem);
this->HandleOctave(fTrem);

if (fTrem->HasUnitdur()) {
LogWarning("FTrem produces incorrect MIDI output");
Expand Down Expand Up @@ -556,8 +556,6 @@ FunctorCode GenerateMIDIFunctor::VisitGraceGrpEnd(const GraceGrp *graceGrp)
m_graceNotes.clear();
}

this->HandleOctaveEnd(graceGrp);

return FUNCTOR_CONTINUE;
}

Expand Down Expand Up @@ -593,7 +591,7 @@ FunctorCode GenerateMIDIFunctor::VisitLayerElement(const LayerElement *layerElem
{
if (layerElement->IsScoreDefElement()) return FUNCTOR_SIBLINGS;

this->HandleOctaveBegin(layerElement);
this->HandleOctave(layerElement);

// Only resolve simple sameas links to avoid infinite recursion
const LayerElement *sameas = dynamic_cast<const LayerElement *>(layerElement->GetSameasLink());
Expand All @@ -604,13 +602,6 @@ FunctorCode GenerateMIDIFunctor::VisitLayerElement(const LayerElement *layerElem
return FUNCTOR_CONTINUE;
}

FunctorCode GenerateMIDIFunctor::VisitLayerElementEnd(const LayerElement *layerElement)
{
this->HandleOctaveEnd(layerElement);

return FUNCTOR_CONTINUE;
}

FunctorCode GenerateMIDIFunctor::VisitMeasure(const Measure *measure)
{
// Here we need to update the m_totalTime from the starting time of the measure.
Expand All @@ -637,7 +628,7 @@ FunctorCode GenerateMIDIFunctor::VisitMRpt(const MRpt *mRpt)

FunctorCode GenerateMIDIFunctor::VisitNote(const Note *note)
{
this->HandleOctaveBegin(note);
this->HandleOctave(note);

// Skip linked notes
if (note->HasSameasLink()) {
Expand Down Expand Up @@ -951,25 +942,38 @@ void GenerateMIDIFunctor::GenerateGraceNoteMIDI(
}
}

void GenerateMIDIFunctor::HandleOctaveBegin(const LayerElement *layerElement)
void GenerateMIDIFunctor::HandleOctave(const LayerElement *layerElement)
{
const auto octaveIter
= std::find_if(m_octaves.begin(), m_octaves.end(), [this, layerElement](const OctaveInfo &octave) {
return ((octave.staffN == m_staffN) && (octave.layerN == m_layerN)
&& (octave.octave->GetStart() == layerElement));
});
// Handle octave end
auto octaveIter = std::find_if(m_octaves.begin(), m_octaves.end(), [this, layerElement](const OctaveInfo &octave) {
if (octave.isActive && (octave.staffN == m_staffN) && (octave.layerN == m_layerN)) {
const Alignment *endAlignment = octave.octave->GetEnd()->GetAlignment();
const Alignment *alignment = layerElement->GetAlignment();
if (endAlignment && alignment) {
return *endAlignment < *alignment;
}
}
return false;
});
if (octaveIter != m_octaves.end()) {
m_octaveShift = octaveIter->octaveShift;
m_octaveShift -= octaveIter->octaveShift;
m_octaves.erase(octaveIter);
}
}

void GenerateMIDIFunctor::HandleOctaveEnd(const LayerElement *layerElement)
{
if (std::any_of(m_octaves.begin(), m_octaves.end(), [this, layerElement](const OctaveInfo &octave) {
return ((octave.staffN == m_staffN) && (octave.layerN == m_layerN)
&& (octave.octave->GetEnd() == layerElement));
})) {
m_octaveShift = 0;
// Handle octave begin
octaveIter = std::find_if(m_octaves.begin(), m_octaves.end(), [this, layerElement](const OctaveInfo &octave) {
if (!octave.isActive && (octave.staffN == m_staffN) && (octave.layerN == m_layerN)) {
const Alignment *startAlignment = octave.octave->GetStart()->GetAlignment();
const Alignment *alignment = layerElement->GetAlignment();
if (startAlignment && alignment) {
return *startAlignment <= *alignment;
}
}
return false;
});
if (octaveIter != m_octaves.end()) {
m_octaveShift += octaveIter->octaveShift;
octaveIter->isActive = true;
}
}

Expand Down

0 comments on commit 0d60320

Please sign in to comment.