Skip to content

Commit 40b0a4a

Browse files
authored
Merge pull request #30808 from lvinken/import_tef_fix_measure_issues
Import tef fix measure issues
2 parents c86de2d + f641449 commit 40b0a4a

19 files changed

+1610
-154
lines changed

src/importexport/tabledit/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ set(MODULE_SRC
2828

2929
${CMAKE_CURRENT_LIST_DIR}/internal/importtef.cpp
3030
${CMAKE_CURRENT_LIST_DIR}/internal/importtef.h
31+
${CMAKE_CURRENT_LIST_DIR}/internal/measurehandler.cpp
32+
${CMAKE_CURRENT_LIST_DIR}/internal/measurehandler.h
33+
${CMAKE_CURRENT_LIST_DIR}/internal/note.cpp
34+
${CMAKE_CURRENT_LIST_DIR}/internal/note.h
3135
${CMAKE_CURRENT_LIST_DIR}/internal/tuplethandler.cpp
3236
${CMAKE_CURRENT_LIST_DIR}/internal/tuplethandler.h
3337
${CMAKE_CURRENT_LIST_DIR}/internal/voiceallocator.cpp

src/importexport/tabledit/internal/importtef.cpp

Lines changed: 108 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
* along with this program. If not, see <https://www.gnu.org/licenses/>.
2121
*/
2222
#include "importtef.h"
23+
#include "measurehandler.h"
2324
#include "tuplethandler.h"
2425

2526
#include "engraving/dom/box.h"
@@ -265,19 +266,20 @@ static void addGraceNotesToChord(mu::engraving::Chord* chord, int pitch, int fre
265266
chord->add(cr);
266267
}
267268

268-
static void addRest(Segment* segment, track_idx_t track, TDuration tDuration, Fraction length, muse::draw::Color color)
269+
static void addRest(Segment* segment, track_idx_t track, TDuration tDuration, Fraction length, muse::draw::Color color, bool visible = true)
269270
{
270271
mu::engraving::Rest* rest = Factory::createRest(segment);
271272
if (rest) {
272273
rest->setTrack(track);
273274
rest->setDurationType(tDuration);
274275
rest->setTicks(length);
275276
rest->setColor(color);
277+
rest->setVisible(visible);
276278
segment->add(rest);
277279
}
278280
}
279281

280-
void TablEdit::createContents()
282+
void TablEdit::createContents(const MeasureHandler& measureHandler)
281283
{
282284
if (tefInstruments.size() == 0) {
283285
LOGD("error: no instruments");
@@ -315,10 +317,14 @@ void TablEdit::createContents()
315317
if (firstNote->dots) {
316318
tDuration.setDots(firstNote->dots);
317319
}
320+
321+
const auto idx { measureHandler.measureIndex(firstNote->position, tefMeasures) };
322+
const Fraction gapCorrection { measureHandler.sumPreviousGaps(idx), 64 };
318323
const auto positionCorrection = tupletHandler.doTuplet(firstNote);
319324

320325
Fraction tick { firstNote->position, 64 }; // position is in 64th
321326
tick += positionCorrection;
327+
tick -= gapCorrection;
322328
LOGN(" positionCorrection %d/%d tick %d/%d length %d/%d",
323329
positionCorrection.numerator(), positionCorrection.denominator(),
324330
tick.numerator(), tick.denominator(),
@@ -413,19 +419,38 @@ void TablEdit::createLinkedTabs()
413419
}
414420
}
415421

416-
void TablEdit::createMeasures()
422+
static Fraction reducedActualLength(const int actual, const int nominalDenominator)
423+
{
424+
Fraction res { actual, 64 };
425+
while (res.denominator() >= 2 * nominalDenominator && res.numerator() % 2 == 0) {
426+
res.setNumerator(res.numerator() / 2);
427+
res.setDenominator(res.denominator() / 2);
428+
}
429+
LOGN("actual %d nominalDenominator %d res %d/%d", actual, nominalDenominator, res.numerator(), res.denominator());
430+
return res;
431+
}
432+
433+
void TablEdit::createMeasures(const MeasureHandler& measureHandler)
417434
{
418435
int lastKey { 0 }; // safe default
419436
Fraction lastTimeSig { -1, -1 }; // impossible value
420437
Fraction tick { 0, 1 };
421-
for (const auto& tefMeasure : tefMeasures) {
438+
for (size_t idx = 0; idx < tefMeasures.size(); ++idx) {
439+
TefMeasure& tefMeasure { tefMeasures.at(idx) };
422440
// create measure
423441
auto measure = Factory::createMeasure(score->dummy()->system());
424442
measure->setTick(tick);
425-
Fraction length{ tefMeasure.numerator, tefMeasure.denominator };
426-
measure->setTimesig(length);
427-
measure->setTicks(length);
443+
Fraction nominalLength{ tefMeasure.numerator, tefMeasure.denominator };
444+
Fraction actualLength{ reducedActualLength(measureHandler.actualSize(tefMeasures, idx), tefMeasure.denominator) };
445+
measure->setTimesig(nominalLength);
446+
measure->setTicks(actualLength);
428447
measure->setEndBarLineType(BarLineType::NORMAL, 0);
448+
LOGN("measure %p tick %d/%d nominalLength %d/%d actualLength %d/%d",
449+
measure,
450+
tick.numerator(), tick.denominator(),
451+
nominalLength.numerator(), nominalLength.denominator(),
452+
actualLength.numerator(), actualLength.denominator()
453+
);
429454
score->measures()->add(measure);
430455

431456
if (tick == Fraction { 0, 1 }) {
@@ -441,11 +466,11 @@ void TablEdit::createMeasures()
441466
auto s2 = measure->getSegment(mu::engraving::SegmentType::TimeSig, tick);
442467
for (size_t i = 0; i < tefInstruments.size(); ++i) {
443468
mu::engraving::TimeSig* timesig = Factory::createTimeSig(s2);
444-
timesig->setSig(length);
469+
timesig->setSig(nominalLength);
445470
timesig->setTrack(i * VOICES);
446471
s2->add(timesig);
447472
}
448-
lastTimeSig = length;
473+
lastTimeSig = nominalLength;
449474
createTempo();
450475
} else {
451476
if (tefMeasure.key != lastKey) {
@@ -458,19 +483,19 @@ void TablEdit::createMeasures()
458483
}
459484
lastKey = tefMeasure.key;
460485
}
461-
if (length != lastTimeSig) {
486+
if (nominalLength != lastTimeSig) {
462487
auto s2 = measure->getSegment(mu::engraving::SegmentType::TimeSig, tick);
463488
for (size_t i = 0; i < tefInstruments.size(); ++i) {
464489
mu::engraving::TimeSig* timesig = Factory::createTimeSig(s2);
465-
timesig->setSig(length);
490+
timesig->setSig(nominalLength);
466491
timesig->setTrack(i * VOICES);
467492
s2->add(timesig);
468493
}
469-
lastTimeSig = length;
494+
lastTimeSig = nominalLength;
470495
}
471496
}
472497

473-
tick += length;
498+
tick += actualLength;
474499
}
475500
score->setUpTempoMap();
476501
}
@@ -569,14 +594,81 @@ static void setInstrumentIDs(const std::vector<Part*>& parts)
569594
}
570595
}
571596

597+
//---------------------------------------------------------
598+
// fillGap
599+
//---------------------------------------------------------
600+
601+
// Fill one gap (tstart - tend) in this track in this measure with rest(s).
602+
603+
static void fillGap(Measure* measure, track_idx_t track, const Fraction& tstart, const Fraction& tend)
604+
{
605+
Fraction ctick = tstart;
606+
Fraction restLen = tend - tstart;
607+
LOGN("measure %p track %zu tstart %d tend %d restLen %d len",
608+
measure, track, tstart.ticks(), tend.ticks(), restLen.ticks());
609+
auto durList = toDurationList(restLen, true);
610+
LOGN("durList.size %zu", durList.size());
611+
for (const auto& dur : durList) {
612+
LOGN("type %d dots %d fraction %d/%d", dur.type(), dur.dots(), dur.fraction().numerator(), dur.fraction().denominator());
613+
Segment* s = measure->getSegment(SegmentType::ChordRest, ctick);
614+
addRest(s, track, dur, dur.fraction(), muse::draw::Color::BLACK, false);
615+
ctick += dur.fraction();
616+
}
617+
}
618+
619+
//---------------------------------------------------------
620+
// fillGapsInFirstVoices
621+
//---------------------------------------------------------
622+
623+
// Fill gaps in first voice of every staff in this measure for this part with rest(s).
624+
625+
static void fillGapsInFirstVoices(MasterScore* score)
626+
{
627+
IF_ASSERT_FAILED(score) {
628+
return;
629+
}
630+
631+
for (staff_idx_t idx = 0; idx < score->nstaves(); ++idx) {
632+
for (Measure* measure = score->firstMeasure(); measure; measure = measure->nextMeasure()) {
633+
Fraction measTick = measure->tick();
634+
Fraction measLen = measure->ticks();
635+
Fraction nextMeasTick = measTick + measLen;
636+
LOGN("measure %p idx %zu tick %d - %d (len %d)",
637+
measure, idx, measTick.ticks(), nextMeasTick.ticks(), measLen.ticks());
638+
track_idx_t track = idx * VOICES;
639+
Fraction endOfLastCR = measTick;
640+
for (Segment* s = measure->first(); s; s = s->next()) {
641+
EngravingItem* el = s->element(track);
642+
if (el) {
643+
if (s->isChordRestType()) {
644+
ChordRest* cr = static_cast<ChordRest*>(el);
645+
Fraction crTick = cr->tick();
646+
Fraction crLen = cr->globalTicks();
647+
if (crTick > endOfLastCR) {
648+
fillGap(measure, track, endOfLastCR, crTick);
649+
}
650+
endOfLastCR = crTick + crLen;
651+
}
652+
}
653+
}
654+
if (nextMeasTick > endOfLastCR) {
655+
fillGap(measure, track, endOfLastCR, nextMeasTick);
656+
}
657+
}
658+
}
659+
}
660+
572661
void TablEdit::createScore()
573662
{
663+
MeasureHandler measureHandler;
664+
measureHandler.calculate(tefContents, tefMeasures);
574665
createProperties();
575666
createParts();
576667
createTitleFrame();
577-
createMeasures();
668+
createMeasures(measureHandler);
578669
createNotesFrame();
579-
createContents();
670+
createContents(measureHandler);
671+
fillGapsInFirstVoices(score);
580672
createRepeats();
581673
createTexts();
582674
createLinkedTabs();
@@ -877,6 +969,7 @@ void TablEdit::readTefMeasures()
877969
for (uint16_t i = 0; i < numberOfMeasures; ++i) {
878970
TefMeasure measure;
879971
measure.flag = readUInt8();
972+
measure.isPickup = measure.flag & 0x08;
880973
/* uint8_t uTmp = */ readUInt8();
881974
measure.key = readInt8();
882975
measure.size = readUInt8();

src/importexport/tabledit/internal/importtef.h

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232
#include "voiceallocator.h"
3333

3434
namespace mu::iex::tabledit {
35+
class MeasureHandler;
36+
3537
// offsets into the file header
3638
static const uint8_t OFFSET_TBED = 0x38;
3739
static const uint8_t OFFSET_CONTENTS = 0x3C;
@@ -54,6 +56,15 @@ enum class Voice : uint8_t {
5456
LOWER = 3 // lower set
5557
};
5658

59+
struct TefMeasure {
60+
int flag { 0 };
61+
bool isPickup { false };
62+
int key { 0 };
63+
int size { 0 };
64+
int numerator { 0 };
65+
int denominator { 0 };
66+
};
67+
5768
struct TefNote {
5869
int position { 0 };
5970
int string { 0 };
@@ -120,14 +131,6 @@ class TablEdit
120131
std::string name;
121132
};
122133

123-
struct TefMeasure {
124-
int flag { 0 };
125-
int key { 0 };
126-
int size { 0 };
127-
int numerator { 0 };
128-
int denominator { 0 };
129-
};
130-
131134
struct TefReadingListItem {
132135
int firstMeasure { 0 };
133136
int lastMeasure { 0 };
@@ -140,9 +143,9 @@ class TablEdit
140143
};
141144

142145
void allocateVoices(std::vector<VoiceAllocator>& allocator);
143-
void createContents();
146+
void createContents(const MeasureHandler& measureHandler);
144147
void createLinkedTabs();
145-
void createMeasures();
148+
void createMeasures(const MeasureHandler& measureHandler);
146149
void createNotesFrame();
147150
void createParts();
148151
void createProperties();

0 commit comments

Comments
 (0)