mirror of
https://github.com/microtherion/VocalEasel.git
synced 2024-12-22 19:23:59 +00:00
Implement tying across measures
This commit is contained in:
parent
a60d6612ff
commit
3e8ba7a75e
|
@ -37,28 +37,23 @@ void VLMMAWriter::VisitMeasure(size_t m, VLProperties & p, VLMeasure & meas)
|
||||||
//
|
//
|
||||||
// Generate melody and account for ties
|
// Generate melody and account for ties
|
||||||
//
|
//
|
||||||
bool setLastDur = false;
|
|
||||||
fAccum.clear();
|
fAccum.clear();
|
||||||
fTied = meas.fMelody.front().fTied & VLNote::kTiedWithPrev;
|
bool tiedWithPrev = (meas.fMelody.front().fTied & VLNote::kTiedWithPrev)
|
||||||
if (fTied && meas.fMelody.size() == 1) {
|
|| fSong->DoesTieWithPrevRepeat(m);
|
||||||
VisitNotes(meas, p, true);
|
bool tiedWithNext = (meas.fMelody.back().fTied & VLNote::kTiedWithNext)
|
||||||
if (meas.fMelody.back().fTied & VLNote::kTiedWithNext) {
|
|| fSong->DoesTieWithNextRepeat(m);
|
||||||
fAccum = "~<>~;";
|
fTied = tiedWithPrev;
|
||||||
} else {
|
VisitNotes(meas, p, true);
|
||||||
fAccum = "~<>;";
|
if (fTied || fAccum == "~") {
|
||||||
}
|
fAccum = tiedWithNext ? "~<>~;" : "~<>;";
|
||||||
} else {
|
} else if (tiedWithNext) {
|
||||||
VisitNotes(meas, p, true);
|
fAccum.replace(fAccum.find_last_of(';'), 0, "~", 1);
|
||||||
if (meas.fMelody.back().fTied & VLNote::kTiedWithNext) {
|
|
||||||
fAccum.replace(fAccum.find_last_of(';'), 0, "~", 1);
|
|
||||||
setLastDur = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string melody = fAccum;
|
std::string melody = fAccum;
|
||||||
|
|
||||||
fMeasures += chords+"\t{ " + melody + " }\n";
|
fMeasures += chords+"\t{ " + melody + " }\n";
|
||||||
if (setLastDur)
|
if (!fTied && tiedWithNext)
|
||||||
fLastDur = fMeasures.find_last_of("123468");
|
fLastDur = fMeasures.find_last_of("123468");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,18 +118,19 @@ void VLMMAWriter::VisitNote(VLLyricsNote & n)
|
||||||
} else if (n.fDuration.fDenom == 24) {
|
} else if (n.fDuration.fDenom == 24) {
|
||||||
dur = "6"; // 16th note triplet
|
dur = "6"; // 16th note triplet
|
||||||
}
|
}
|
||||||
if (n.fTied & VLNote::kTiedWithPrev) {
|
if (fTied) {
|
||||||
if (fTied) {
|
fMeasures.replace(fLastDur+1, 0, '+'+dur);
|
||||||
fMeasures.replace(fLastDur+1, 0, '+'+dur);
|
fLastDur += 1+dur.size();
|
||||||
if (!(n.fTied & VLNote::kTiedWithNext))
|
if (!(n.fTied & VLNote::kTiedWithNext)) {
|
||||||
fAccum += "~";
|
fAccum += "~";
|
||||||
} else {
|
fTied = false;
|
||||||
size_t d = fAccum.find_last_of("123468");
|
|
||||||
fAccum.replace(d+1, 0, '+'+dur);
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
} else if (n.fTied & VLNote::kTiedWithPrev) {
|
||||||
|
size_t d = fAccum.find_last_of("123468");
|
||||||
|
fAccum.replace(d+1, 0, '+'+dur);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
fTied = false;
|
|
||||||
if (fAccum.size() > 1)
|
if (fAccum.size() > 1)
|
||||||
fAccum += ' ';
|
fAccum += ' ';
|
||||||
fAccum += dur+MMAPitchName(n.fPitch, fUseSharps, true)+MMAOctave(n.fPitch)+';';
|
fAccum += dur+MMAPitchName(n.fPitch, fUseSharps, true)+MMAOctave(n.fPitch)+';';
|
||||||
|
|
|
@ -1360,21 +1360,22 @@ void VLSong::SetWord(size_t stanza, size_t measure, VLFraction at, std::string w
|
||||||
|
|
||||||
void VLSong::AddRepeat(size_t beginMeasure, size_t endMeasure, int times)
|
void VLSong::AddRepeat(size_t beginMeasure, size_t endMeasure, int times)
|
||||||
{
|
{
|
||||||
for (size_t r=0; r<fRepeats.size(); ++r)
|
for (size_t r=0; r<fRepeats.size(); ++r) {
|
||||||
if (fRepeats[r].fEndings[0].fBegin == beginMeasure
|
VLRepeat & rp = fRepeats[r];
|
||||||
&& fRepeats[r].fEndings[0].fEnd >= endMeasure
|
if (rp.fEndings[0].fBegin == beginMeasure
|
||||||
|
&& rp.fEndings[0].fEnd >= endMeasure
|
||||||
)
|
)
|
||||||
if (fRepeats[r].fEndings[0].fEnd == endMeasure) {
|
if (rp.fEndings[0].fEnd == endMeasure) {
|
||||||
//
|
//
|
||||||
// Exact match, just change times
|
// Exact match, just change times
|
||||||
//
|
//
|
||||||
size_t mask = ((1<<times)-1) ^ ((1<<fRepeats[r].fTimes)-1);
|
size_t mask = ((1<<times)-1) ^ ((1<<rp.fTimes)-1);
|
||||||
if (fRepeats[r].fTimes < times)
|
if (rp.fTimes < times)
|
||||||
fRepeats[r].fEndings[0].fVolta |= mask;
|
rp.fEndings[0].fVolta |= mask;
|
||||||
else if (fRepeats[r].fTimes > times)
|
else if (rp.fTimes > times)
|
||||||
for (size_t e=0; e<fRepeats[r].fEndings.size(); ++e)
|
for (size_t e=0; e<rp.fEndings.size(); ++e)
|
||||||
fRepeats[r].fEndings[e].fVolta &= ~mask;
|
rp.fEndings[e].fVolta &= ~mask;
|
||||||
fRepeats[r].fTimes = times;
|
rp.fTimes = times;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1382,6 +1383,7 @@ void VLSong::AddRepeat(size_t beginMeasure, size_t endMeasure, int times)
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
VLRepeat rep;
|
VLRepeat rep;
|
||||||
|
|
||||||
|
@ -1393,82 +1395,87 @@ void VLSong::AddRepeat(size_t beginMeasure, size_t endMeasure, int times)
|
||||||
|
|
||||||
void VLSong::DelRepeat(size_t beginMeasure, size_t endMeasure)
|
void VLSong::DelRepeat(size_t beginMeasure, size_t endMeasure)
|
||||||
{
|
{
|
||||||
for (size_t r=0; r<fRepeats.size(); ++r)
|
for (size_t r=0; r<fRepeats.size(); ++r) {
|
||||||
if (fRepeats[r].fEndings[0].fBegin == beginMeasure
|
VLRepeat & rp = fRepeats[r];
|
||||||
&& fRepeats[r].fEndings[0].fEnd >= endMeasure
|
if (rp.fEndings[0].fBegin == beginMeasure
|
||||||
|
&& rp.fEndings[0].fEnd >= endMeasure
|
||||||
) {
|
) {
|
||||||
fRepeats.erase(fRepeats.begin()+r);
|
fRepeats.erase(fRepeats.begin()+r);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VLSong::AddEnding(size_t beginMeasure, size_t endMeasure, size_t volta)
|
void VLSong::AddEnding(size_t beginMeasure, size_t endMeasure, size_t volta)
|
||||||
{
|
{
|
||||||
for (size_t r=0; r<fRepeats.size(); ++r)
|
for (size_t r=0; r<fRepeats.size(); ++r) {
|
||||||
if (fRepeats[r].fEndings[0].fBegin < beginMeasure
|
VLRepeat & rp = fRepeats[r];
|
||||||
&& fRepeats[r].fEndings[0].fEnd >= beginMeasure
|
if (rp.fEndings[0].fBegin < beginMeasure
|
||||||
|
&& rp.fEndings[0].fEnd >= beginMeasure
|
||||||
) {
|
) {
|
||||||
VLRepeat & repeat = fRepeats[r];
|
for (size_t e=1; e<rp.fEndings.size(); ++e)
|
||||||
for (size_t e=1; e<repeat.fEndings.size(); ++e)
|
if (rp.fEndings[e].fBegin == beginMeasure
|
||||||
if (repeat.fEndings[e].fBegin == beginMeasure
|
&& rp.fEndings[e].fEnd == endMeasure
|
||||||
&& repeat.fEndings[e].fEnd == endMeasure
|
|
||||||
) {
|
) {
|
||||||
//
|
//
|
||||||
// Found it, just edit volta
|
// Found it, just edit volta
|
||||||
//
|
//
|
||||||
repeat.fEndings[0].fVolta |= repeat.fEndings[e].fVolta;
|
rp.fEndings[0].fVolta |= rp.fEndings[e].fVolta;
|
||||||
volta &= repeat.fEndings[0].fVolta;
|
volta &= rp.fEndings[0].fVolta;
|
||||||
repeat.fEndings[0].fVolta &= ~volta;
|
rp.fEndings[0].fVolta &= ~volta;
|
||||||
repeat.fEndings[e].fVolta = volta;
|
rp.fEndings[e].fVolta = volta;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// Not found, add new ending
|
// Not found, add new ending
|
||||||
//
|
//
|
||||||
volta &= fRepeats[r].fEndings[0].fVolta;
|
volta &= rp.fEndings[0].fVolta;
|
||||||
fRepeats[r].fEndings[0].fVolta &= ~volta;
|
rp.fEndings[0].fVolta &= ~volta;
|
||||||
fRepeats[r].fEndings[0].fEnd =
|
rp.fEndings[0].fEnd =
|
||||||
std::max<int8_t>(fRepeats[r].fEndings[0].fEnd, endMeasure);
|
std::max<int8_t>(rp.fEndings[0].fEnd, endMeasure);
|
||||||
fRepeats[r].fEndings.push_back(
|
rp.fEndings.push_back(
|
||||||
VLRepeat::Ending(beginMeasure, endMeasure, volta));
|
VLRepeat::Ending(beginMeasure, endMeasure, volta));
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VLSong::DelEnding(size_t beginMeasure, size_t endMeasure)
|
void VLSong::DelEnding(size_t beginMeasure, size_t endMeasure)
|
||||||
{
|
{
|
||||||
for (size_t r=0; r<fRepeats.size(); ++r)
|
for (size_t r=0; r<fRepeats.size(); ++r) {
|
||||||
if (fRepeats[r].fEndings[0].fBegin <= beginMeasure
|
VLRepeat & rp = fRepeats[r];
|
||||||
&& fRepeats[r].fEndings[0].fEnd > beginMeasure
|
if (rp.fEndings[0].fBegin <= beginMeasure
|
||||||
|
&& rp.fEndings[0].fEnd > beginMeasure
|
||||||
)
|
)
|
||||||
for (size_t e=1; e<fRepeats[r].fEndings.size(); ++e)
|
for (size_t e=1; e<rp.fEndings.size(); ++e)
|
||||||
if (fRepeats[r].fEndings[e].fBegin == beginMeasure) {
|
if (rp.fEndings[e].fBegin == beginMeasure) {
|
||||||
fRepeats[r].fEndings[0].fVolta |= fRepeats[r].fEndings[e].fVolta;
|
rp.fEndings[0].fVolta |= rp.fEndings[e].fVolta;
|
||||||
if (e > 1 && e == fRepeats[r].fEndings.size()-1)
|
if (e > 1 && e == rp.fEndings.size()-1)
|
||||||
fRepeats[r].fEndings[0].fEnd = fRepeats[r].fEndings[e].fBegin;
|
rp.fEndings[0].fEnd = rp.fEndings[e].fBegin;
|
||||||
fRepeats[r].fEndings.erase(fRepeats[r].fEndings.begin()+e);
|
rp.fEndings.erase(rp.fEndings.begin()+e);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VLSong::CanBeRepeat(size_t beginMeasure, size_t endMeasure, int * times)
|
bool VLSong::CanBeRepeat(size_t beginMeasure, size_t endMeasure, int * times)
|
||||||
{
|
{
|
||||||
for (size_t r=0; r<fRepeats.size(); ++r) {
|
for (size_t r=0; r<fRepeats.size(); ++r) {
|
||||||
const VLRepeat & rep = fRepeats[r];
|
VLRepeat & rp = fRepeats[r];
|
||||||
if (rep.fEndings[0].fBegin == beginMeasure) {
|
if (rp.fEndings[0].fBegin == beginMeasure) {
|
||||||
//
|
//
|
||||||
// Look for exact match & return
|
// Look for exact match & return
|
||||||
//
|
//
|
||||||
if (times)
|
if (times)
|
||||||
*times = fRepeats[r].fTimes;
|
*times = rp.fTimes;
|
||||||
if (rep.fEndings[0].fEnd == endMeasure)
|
if (rp.fEndings[0].fEnd == endMeasure)
|
||||||
return true;
|
return true;
|
||||||
if (rep.fEndings.size() > 1) {
|
if (rp.fEndings.size() > 1) {
|
||||||
if (rep.fEndings[1].fBegin == endMeasure)
|
if (rp.fEndings[1].fBegin == endMeasure)
|
||||||
return true;
|
return true;
|
||||||
if (rep.fEndings[1].fEnd == endMeasure)
|
if (rp.fEndings[1].fEnd == endMeasure)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1476,23 +1483,23 @@ bool VLSong::CanBeRepeat(size_t beginMeasure, size_t endMeasure, int * times)
|
||||||
// Inclusions and surroundings are OK. Beginnings may match, but
|
// Inclusions and surroundings are OK. Beginnings may match, but
|
||||||
// endings must not.
|
// endings must not.
|
||||||
//
|
//
|
||||||
if (rep.fEndings[0].fBegin >= beginMeasure
|
if (rp.fEndings[0].fBegin >= beginMeasure
|
||||||
&& rep.fEndings[0].fEnd < endMeasure
|
&& rp.fEndings[0].fEnd < endMeasure
|
||||||
)
|
)
|
||||||
continue;
|
continue;
|
||||||
if (rep.fEndings[0].fBegin <= beginMeasure
|
if (rp.fEndings[0].fBegin <= beginMeasure
|
||||||
&& rep.fEndings[0].fEnd > endMeasure
|
&& rp.fEndings[0].fEnd > endMeasure
|
||||||
)
|
)
|
||||||
continue;
|
continue;
|
||||||
//
|
//
|
||||||
// Look for overlap and reject
|
// Look for overlap and reject
|
||||||
//
|
//
|
||||||
if (fRepeats[r].fEndings[0].fBegin >= beginMeasure
|
if (rp.fEndings[0].fBegin >= beginMeasure
|
||||||
&& fRepeats[r].fEndings[0].fBegin < endMeasure
|
&& rp.fEndings[0].fBegin < endMeasure
|
||||||
)
|
)
|
||||||
return false;
|
return false;
|
||||||
if (fRepeats[r].fEndings[0].fEnd > beginMeasure
|
if (rp.fEndings[0].fEnd > beginMeasure
|
||||||
&& fRepeats[r].fEndings[0].fEnd <= endMeasure
|
&& rp.fEndings[0].fEnd <= endMeasure
|
||||||
)
|
)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1507,19 +1514,18 @@ bool VLSong::CanBeRepeat(size_t beginMeasure, size_t endMeasure, int * times)
|
||||||
bool VLSong::CanBeEnding(size_t beginMeasure, size_t endMeasure,
|
bool VLSong::CanBeEnding(size_t beginMeasure, size_t endMeasure,
|
||||||
size_t * volta, size_t * voltaOK)
|
size_t * volta, size_t * voltaOK)
|
||||||
{
|
{
|
||||||
for (size_t r=0; r<fRepeats.size(); ++r)
|
for (size_t r=0; r<fRepeats.size(); ++r) {
|
||||||
if (beginMeasure > fRepeats[r].fEndings[0].fBegin
|
VLRepeat & rp = fRepeats[r];
|
||||||
&& beginMeasure <= fRepeats[r].fEndings[0].fEnd
|
if (beginMeasure > rp.fEndings[0].fBegin
|
||||||
|
&& beginMeasure <= rp.fEndings[0].fEnd
|
||||||
) {
|
) {
|
||||||
//
|
//
|
||||||
// Found right repeat
|
// Found right repeat
|
||||||
//
|
//
|
||||||
VLRepeat & repeat = fRepeats[r];
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Append new repeat, or carve out from ending
|
// Append new repeat, or carve out from ending
|
||||||
//
|
//
|
||||||
if (beginMeasure == repeat.fEndings[0].fEnd) {
|
if (beginMeasure == rp.fEndings[0].fEnd) {
|
||||||
for (size_t r2=0; r2<fRepeats.size(); ++r2)
|
for (size_t r2=0; r2<fRepeats.size(); ++r2)
|
||||||
if (r2 != r
|
if (r2 != r
|
||||||
&& fRepeats[r2].fEndings[0].fBegin >= beginMeasure
|
&& fRepeats[r2].fEndings[0].fBegin >= beginMeasure
|
||||||
|
@ -1527,89 +1533,96 @@ bool VLSong::CanBeEnding(size_t beginMeasure, size_t endMeasure,
|
||||||
)
|
)
|
||||||
return false; // Overlap
|
return false; // Overlap
|
||||||
if (volta)
|
if (volta)
|
||||||
*volta = repeat.fEndings[0].fVolta;
|
*volta = rp.fEndings[0].fVolta;
|
||||||
if (voltaOK)
|
if (voltaOK)
|
||||||
*voltaOK = repeat.fEndings[0].fVolta;
|
*voltaOK = rp.fEndings[0].fVolta;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} else if (repeat.fEndings.size() == 1
|
} else if (rp.fEndings.size() == 1
|
||||||
&& endMeasure >= repeat.fEndings[0].fEnd
|
&& endMeasure >= rp.fEndings[0].fEnd
|
||||||
) {
|
) {
|
||||||
if (volta)
|
if (volta)
|
||||||
*volta = repeat.fEndings[0].fVolta;
|
*volta = rp.fEndings[0].fVolta;
|
||||||
if (voltaOK)
|
if (voltaOK)
|
||||||
*voltaOK = repeat.fEndings[0].fVolta;
|
*voltaOK = rp.fEndings[0].fVolta;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// Otherwise must match existing
|
// Otherwise must match existing
|
||||||
//
|
//
|
||||||
for (size_t e=1; e<repeat.fEndings.size(); ++e)
|
for (size_t e=1; e<rp.fEndings.size(); ++e)
|
||||||
if (beginMeasure == repeat.fEndings[e].fBegin
|
if (beginMeasure == rp.fEndings[e].fBegin
|
||||||
&& endMeasure == repeat.fEndings[e].fEnd
|
&& endMeasure == rp.fEndings[e].fEnd
|
||||||
) {
|
) {
|
||||||
if (volta)
|
if (volta)
|
||||||
*volta = repeat.fEndings[e].fVolta;
|
*volta = rp.fEndings[e].fVolta;
|
||||||
if (voltaOK)
|
if (voltaOK)
|
||||||
*voltaOK = repeat.fEndings[e].fVolta
|
*voltaOK = rp.fEndings[e].fVolta
|
||||||
| repeat.fEndings[0].fVolta;
|
| rp.fEndings[0].fVolta;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VLSong::DoesBeginRepeat(size_t measure, int * times) const
|
bool VLSong::DoesBeginRepeat(size_t measure, int * times) const
|
||||||
{
|
{
|
||||||
for (size_t r=0; r<fRepeats.size(); ++r)
|
for (size_t r=0; r<fRepeats.size(); ++r) {
|
||||||
if (fRepeats[r].fEndings[0].fBegin == measure) {
|
const VLRepeat & rp = fRepeats[r];
|
||||||
|
if (rp.fEndings[0].fBegin == measure) {
|
||||||
if (times)
|
if (times)
|
||||||
*times = fRepeats[r].fTimes;
|
*times = rp.fTimes;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VLSong::DoesEndRepeat(size_t measure, int * times) const
|
bool VLSong::DoesEndRepeat(size_t measure, int * times) const
|
||||||
{
|
{
|
||||||
for (size_t r=0; r<fRepeats.size(); ++r)
|
for (size_t r=0; r<fRepeats.size(); ++r) {
|
||||||
if (fRepeats[r].fEndings[0].fEnd == measure
|
const VLRepeat & rp = fRepeats[r];
|
||||||
&& fRepeats[r].fEndings.size() == 1
|
if (rp.fEndings[0].fEnd == measure
|
||||||
|
&& rp.fEndings.size() == 1
|
||||||
) {
|
) {
|
||||||
if (times)
|
if (times)
|
||||||
*times = fRepeats[r].fTimes;
|
*times = rp.fTimes;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VLSong::DoesBeginEnding(size_t measure, bool * repeat, size_t * volta) const
|
bool VLSong::DoesBeginEnding(size_t measure, bool * repeat, size_t * volta) const
|
||||||
{
|
{
|
||||||
for (size_t r=0; r<fRepeats.size(); ++r)
|
for (size_t r=0; r<fRepeats.size(); ++r) {
|
||||||
if (fRepeats[r].fEndings[0].fEnd >= measure
|
const VLRepeat & rp = fRepeats[r];
|
||||||
&& fRepeats[r].fEndings.size() > 1
|
if (rp.fEndings[0].fBegin < measure
|
||||||
|
&& rp.fEndings[0].fEnd >= measure
|
||||||
|
&& rp.fEndings.size() > 1
|
||||||
) {
|
) {
|
||||||
size_t v = (1<<fRepeats[r].fTimes)-1;
|
size_t v = (1<<rp.fTimes)-1;
|
||||||
for (size_t e=1; e<fRepeats[r].fEndings.size(); ++e)
|
for (size_t e=1; e<rp.fEndings.size(); ++e)
|
||||||
if (fRepeats[r].fEndings[e].fBegin == measure) {
|
if (rp.fEndings[e].fBegin == measure) {
|
||||||
if (repeat)
|
if (repeat)
|
||||||
if (e == fRepeats[r].fEndings.size()-1
|
if (e == rp.fEndings.size()-1
|
||||||
&& fRepeats[r].fEndings[e].fVolta == v
|
&& rp.fEndings[e].fVolta == v
|
||||||
)
|
)
|
||||||
*repeat = false; // Not after last alternative
|
*repeat = false; // Not after last alternative
|
||||||
else
|
else
|
||||||
*repeat = true;
|
*repeat = true;
|
||||||
if (volta)
|
if (volta)
|
||||||
*volta = fRepeats[r].fEndings[e].fVolta;
|
*volta = rp.fEndings[e].fVolta;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} else
|
} else
|
||||||
v &= ~fRepeats[r].fEndings[e].fVolta;
|
v &= ~rp.fEndings[e].fVolta;
|
||||||
if (v && fRepeats[r].fEndings[0].fEnd == measure) {
|
if (v && rp.fEndings[0].fEnd == measure) {
|
||||||
//
|
//
|
||||||
// Implied ending for all not mentioned
|
// Implied ending for all not mentioned
|
||||||
//
|
//
|
||||||
|
@ -1621,31 +1634,34 @@ bool VLSong::DoesBeginEnding(size_t measure, bool * repeat, size_t * volta) cons
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VLSong::DoesEndEnding(size_t measure, bool * repeat, size_t * volta) const
|
bool VLSong::DoesEndEnding(size_t measure, bool * repeat, size_t * volta) const
|
||||||
{
|
{
|
||||||
for (size_t r=0; r<fRepeats.size(); ++r)
|
for (size_t r=0; r<fRepeats.size(); ++r) {
|
||||||
if (fRepeats[r].fEndings[0].fEnd+1 >= measure
|
const VLRepeat & rp = fRepeats[r];
|
||||||
&& fRepeats[r].fEndings.size() > 1
|
if (rp.fEndings[0].fBegin < measure
|
||||||
|
&& rp.fEndings[0].fEnd+1 >= measure
|
||||||
|
&& rp.fEndings.size() > 1
|
||||||
) {
|
) {
|
||||||
size_t v = (1<<fRepeats[r].fTimes)-1;
|
size_t v = (1<<rp.fTimes)-1;
|
||||||
for (size_t e=1; e<fRepeats[r].fEndings.size(); ++e)
|
for (size_t e=1; e<rp.fEndings.size(); ++e)
|
||||||
if (fRepeats[r].fEndings[e].fEnd == measure) {
|
if (rp.fEndings[e].fEnd == measure) {
|
||||||
if (repeat)
|
if (repeat)
|
||||||
if (e == fRepeats[r].fEndings.size()-1
|
if (e == rp.fEndings.size()-1
|
||||||
&& fRepeats[r].fEndings[e].fVolta == v
|
&& rp.fEndings[e].fVolta == v
|
||||||
)
|
)
|
||||||
*repeat = false; // Not after last alternative
|
*repeat = false; // Not after last alternative
|
||||||
else
|
else
|
||||||
*repeat = true;
|
*repeat = true;
|
||||||
if (volta)
|
if (volta)
|
||||||
*volta = fRepeats[r].fEndings[e].fVolta;
|
*volta = rp.fEndings[e].fVolta;
|
||||||
return true;
|
return true;
|
||||||
} else
|
} else
|
||||||
v &= ~fRepeats[r].fEndings[e].fVolta;
|
v &= ~rp.fEndings[e].fVolta;
|
||||||
if (v && fRepeats[r].fEndings[0].fEnd+1 == measure) {
|
if (v && rp.fEndings[0].fEnd+1 == measure) {
|
||||||
//
|
//
|
||||||
// Implied ending for all not mentioned
|
// Implied ending for all not mentioned
|
||||||
//
|
//
|
||||||
|
@ -1657,6 +1673,56 @@ bool VLSong::DoesEndEnding(size_t measure, bool * repeat, size_t * volta) const
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VLSong::DoesTieWithPrevRepeat(size_t measure) const
|
||||||
|
{
|
||||||
|
if (fMeasures[measure].fMelody.front().fPitch == VLNote::kNoPitch)
|
||||||
|
return false; // Rests don't tie
|
||||||
|
for (size_t r=0; r<fRepeats.size(); ++r) {
|
||||||
|
const VLRepeat & rp = fRepeats[r];
|
||||||
|
if (rp.fEndings[0].fBegin < measure
|
||||||
|
&& rp.fEndings[0].fEnd >= measure
|
||||||
|
&& rp.fEndings.size() > 1
|
||||||
|
) {
|
||||||
|
size_t v = (1<<rp.fTimes)-1;
|
||||||
|
int8_t firstEnding = rp.fEndings[0].fEnd;
|
||||||
|
bool doesStartEnding = false;
|
||||||
|
for (size_t e=1; e<rp.fEndings.size(); ++e) {
|
||||||
|
firstEnding = std::min(firstEnding, rp.fEndings[e].fBegin);
|
||||||
|
if (rp.fEndings[e].fBegin == measure)
|
||||||
|
doesStartEnding = true;
|
||||||
|
else
|
||||||
|
v &= ~rp.fEndings[e].fVolta;
|
||||||
|
}
|
||||||
|
if (doesStartEnding || (v && rp.fEndings[0].fEnd == measure))
|
||||||
|
return fMeasures[firstEnding-1].fMelody.back().fTied
|
||||||
|
& VLNote::kTiedWithNext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VLSong::DoesTieWithNextRepeat(size_t measure) const
|
||||||
|
{
|
||||||
|
if (fMeasures[measure].fMelody.back().fPitch == VLNote::kNoPitch)
|
||||||
|
return false; // Rests don't tie
|
||||||
|
for (size_t r=0; r<fRepeats.size(); ++r) {
|
||||||
|
const VLRepeat & rp = fRepeats[r];
|
||||||
|
if (rp.fEndings[0].fBegin < measure
|
||||||
|
&& rp.fEndings[0].fEnd >= measure
|
||||||
|
&& rp.fEndings.size() > 1
|
||||||
|
) {
|
||||||
|
for (size_t e=1; e<rp.fEndings.size(); ++e) {
|
||||||
|
if (rp.fEndings[e].fEnd == measure+1)
|
||||||
|
return !(rp.fEndings[e].fVolta & (1<<(rp.fTimes-1)))
|
||||||
|
&& (fMeasures[rp.fEndings[0].fBegin].fMelody.front().fTied
|
||||||
|
& VLNote::kTiedWithPrev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1742,18 +1808,19 @@ VLSong VLSong::CopyMeasures(size_t beginMeasure, size_t endMeasure)
|
||||||
for (size_t i=0; i<subSong.fMeasures.size(); ++i)
|
for (size_t i=0; i<subSong.fMeasures.size(); ++i)
|
||||||
subSong.fMeasures[i].fPropIdx -= firstProp;
|
subSong.fMeasures[i].fPropIdx -= firstProp;
|
||||||
|
|
||||||
for (size_t r=0; r<fRepeats.size(); ++r)
|
for (size_t r=0; r<fRepeats.size(); ++r) {
|
||||||
if (fRepeats[r].fEndings[0].fBegin >= beginMeasure
|
VLRepeat & rp = fRepeats[r];
|
||||||
&& fRepeats[r].fEndings[0].fEnd <= endMeasure
|
if (rp.fEndings[0].fBegin >= beginMeasure
|
||||||
|
&& rp.fEndings[0].fEnd <= endMeasure
|
||||||
) {
|
) {
|
||||||
VLRepeat repeat = fRepeats[r];
|
for (size_t e=0; e<rp.fEndings.size(); ++e) {
|
||||||
for (size_t e=0; e<repeat.fEndings.size(); ++e) {
|
rp.fEndings[e].fBegin -= beginMeasure;
|
||||||
repeat.fEndings[e].fBegin -= beginMeasure;
|
rp.fEndings[e].fEnd -= endMeasure;
|
||||||
repeat.fEndings[e].fEnd -= endMeasure;
|
|
||||||
}
|
}
|
||||||
subSong.fRepeats.push_back(repeat);
|
subSong.fRepeats.push_back(rp);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return subSong;
|
return subSong;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -130,7 +130,7 @@ struct VLNote {
|
||||||
enum {
|
enum {
|
||||||
kNotTied = 0,
|
kNotTied = 0,
|
||||||
kTiedWithNext = 1,
|
kTiedWithNext = 1,
|
||||||
kTiedWithPrev = 2
|
kTiedWithPrev = 2,
|
||||||
};
|
};
|
||||||
//
|
//
|
||||||
// Hint at visual representation (Computed in DecomposeNotes)
|
// Hint at visual representation (Computed in DecomposeNotes)
|
||||||
|
@ -332,6 +332,8 @@ public:
|
||||||
bool DoesEndRepeat(size_t measure, int * times = 0) const;
|
bool DoesEndRepeat(size_t measure, int * times = 0) const;
|
||||||
bool DoesBeginEnding(size_t measure, bool * repeat = 0, size_t * volta = 0) const;
|
bool DoesBeginEnding(size_t measure, bool * repeat = 0, size_t * volta = 0) const;
|
||||||
bool DoesEndEnding(size_t measure, bool * repeat = 0, size_t * volta = 0) const;
|
bool DoesEndEnding(size_t measure, bool * repeat = 0, size_t * volta = 0) const;
|
||||||
|
bool DoesTieWithPrevRepeat(size_t measure) const;
|
||||||
|
bool DoesTieWithNextRepeat(size_t measure) const;
|
||||||
bool IsNonEmpty() const;
|
bool IsNonEmpty() const;
|
||||||
void ChangeKey(int newKey, bool newMode, bool transpose);
|
void ChangeKey(int newKey, bool newMode, bool transpose);
|
||||||
void ChangeDivisions(int newDivisions);
|
void ChangeDivisions(int newDivisions);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user