1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
|
#include "importmidi_tuplet_tonotes.h"
#include "importmidi_tuplet.h"
#include "importmidi_fraction.h"
#include "importmidi_inner.h"
#include "libmscore/staff.h"
#include "libmscore/score.h"
#include "libmscore/fraction.h"
#include "libmscore/duration.h"
#include "libmscore/measure.h"
#include "libmscore/tuplet.h"
#include "libmscore/mscore.h"
#include "libmscore/chordrest.h"
namespace Ms {
namespace MidiTuplet {
void addElementToTuplet(int voice,
const ReducedFraction &onTime,
const ReducedFraction &len,
DurationElement *el,
std::multimap<ReducedFraction, TupletData> &tuplets)
{
const auto foundTuplets = findTupletsForTimeRange(voice, onTime, len, tuplets, true);
#ifdef IMPORTMIDI_DEBUG
if (foundTuplets.size() > 1) {
qDebug() << "Measure number (from 1):" << el->measure()->no() + 1
<< ", staff index (from 0):" << el->staff()->idx();
Q_ASSERT_X(false, "MidiTuplet::addElementToTuplet",
"More than one tuplet contains specified duration");
}
#endif
if (!foundTuplets.empty()) {
auto &tuplet = const_cast<TupletData &>(foundTuplets.front()->second);
tuplet.elements.push_back(el); // add chord/rest to the tuplet
}
}
void createTupletNotes(
Staff *staff,
const std::multimap<ReducedFraction, TupletData> &tuplets)
{
Score* score = staff->score();
const int track = staff->idx() * VOICES;
for (const auto &tupletEvent: tuplets) {
const auto &tupletData = tupletEvent.second;
if (tupletData.elements.empty())
continue;
Tuplet* tuplet = new Tuplet(score);
const auto &tupletRatio = tupletLimits(tupletData.tupletNumber).ratio;
tuplet->setRatio(tupletRatio.fraction());
tuplet->setDuration(tupletData.len.fraction());
const TDuration baseLen = tupletData.len.fraction() / tupletRatio.denominator();
tuplet->setBaseLen(baseLen);
tuplet->setTrack(track);
tuplet->setTick(tupletData.onTime.ticks());
tuplet->setVoice(tupletData.voice);
Measure* measure = score->tick2measure(tupletData.onTime.ticks());
tuplet->setParent(measure);
for (DurationElement *el: tupletData.elements) {
tuplet->add(el);
el->setTuplet(tuplet);
}
}
}
#ifdef IMPORTMIDI_DEBUG
void printInvalidTupletLocation(int measureIndex, int staffIndex)
{
qDebug() << "Tuplet is invalid; measure number (from 1):"
<< measureIndex + 1
<< ", staff index (from 0):" << staffIndex;
}
bool haveTupletsEnoughElements(const Staff *staff)
{
const int strack = staff->idx() * VOICES;
for (int voice = 0; voice < VOICES; ++voice) {
for (Segment *seg = staff->score()->firstSegment(); seg; seg = seg->next1()) {
if (seg->segmentType() == Segment::Type::ChordRest) {
const ChordRest *cr = static_cast<ChordRest *>(seg->element(strack + voice));
if (!cr)
continue;
const Tuplet *tuplet = cr->tuplet();
if (tuplet) {
if (tuplet->elements().size() <= 1) {
printInvalidTupletLocation(seg->measure()->no(), staff->idx());
return false;
}
int chordCount = 0;
for (const auto &e: tuplet->elements()) {
const ChordRest *cr = static_cast<ChordRest *>(e);
if (cr && cr->type() == Element::Type::CHORD)
++chordCount;
}
if (chordCount == 0) {
printInvalidTupletLocation(seg->measure()->no(), staff->idx());
return false;
}
}
}
}
}
return true;
}
#endif
} // namespace MidiTuplet
} // namespace Ms
|