Skip to content

Commit c60d633

Browse files
committed
Local/global time fixes
1 parent e0032d3 commit c60d633

File tree

6 files changed

+55
-61
lines changed

6 files changed

+55
-61
lines changed

src/engraving/dom/paste.cpp

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ void Score::pasteChordRest(ChordRest* cr, const Fraction& t)
102102
Transpose::transposeChord(chord, tick);
103103
if (chord->tremoloTwoChord()) {
104104
twoNoteTremoloFactor = 2;
105-
} else if (cr->durationTypeTicks() == (cr->actualTicksAt(tick) * 2)) {
105+
} else if (cr->durationTypeTicks() == (cr->ticks() * 2)) {
106106
// this could be the 2nd note of a two-note tremolo
107107
// check previous CR on same track, if it has a two-note tremolo, then set twoNoteTremoloFactor to 2
108108
Segment* seg = measure->undoGetSegment(SegmentType::ChordRest, tick);
@@ -122,7 +122,7 @@ void Score::pasteChordRest(ChordRest* cr, const Fraction& t)
122122
// otherwise, we need to convert to duration rest(s)
123123
// and potentially split the rest up (eg, 5/4 => whole + quarter)
124124
bool convertMeasureRest = cr->isRest() && cr->durationType().type() == DurationType::V_MEASURE
125-
&& (tick != measure->tick() || cr->ticks() != measure->ticks());
125+
&& (tick != measure->tick() || cr->actualTicksAt(tick) != measure->ticks());
126126

127127
Fraction measureEnd = measure->endTick();
128128
bool isGrace = cr->isChord() && toChord(cr)->noteType() != NoteType::NORMAL;
@@ -145,40 +145,39 @@ void Score::pasteChordRest(ChordRest* cr, const Fraction& t)
145145
if (cr->isMeasureRepeat()) {
146146
partialCopy = toMeasureRepeat(cr)->actualTicks() != measure->ticks();
147147
} else if (!isGrace && !cr->tuplet()) {
148-
partialCopy = cr->durationTypeTicks() != (cr->actualTicksAt(tick) * twoNoteTremoloFactor);
148+
partialCopy = cr->durationTypeTicks() != (cr->ticks() * twoNoteTremoloFactor);
149149
}
150150

151151
// if note is too long to fit in measure, split it up with a tie across the barline
152152
// exclude tuplets from consideration
153153
// we have already disallowed a tuplet from crossing the barline, so there is no problem here
154154
// but due to rounding, it might appear from actualTicks() that the last note is too long by a couple of ticks
155155

156+
Staff* stf = cr->staff();
156157
if (!isGrace && !cr->tuplet() && (tick + cr->actualTicksAt(tick) > measureEnd || partialCopy || convertMeasureRest)) {
157158
if (cr->isChord()) {
158159
// split Chord
159160
Chord* c = toChord(cr);
160-
Fraction rest = c->actualTicksAt(tick);
161+
Fraction rest = c->ticks();
161162
bool firstpart = true;
162163
while (rest.isNotZero()) {
163164
measure = tick2measure(tick);
164165
Chord* c2 = firstpart ? c : toChord(c->clone());
165166
if (!firstpart) {
166167
c2->removeMarkings(true);
167168
}
168-
Fraction mlen = measure->endTick() - tick;
169+
Fraction timeStretch = stf->timeStretch(tick);
170+
Fraction mlen = (measure->endTick() - tick) * timeStretch;
169171
Fraction len = mlen > rest ? rest : mlen;
170-
Fraction timeStretch = c2->staff()->timeStretch(tick);
171-
std::vector<TDuration> dl = toRhythmicDurationList(len * timeStretch, false, (tick - measure->tick()) * timeStretch,
172+
std::vector<TDuration> dl = toRhythmicDurationList(len, false, (tick - measure->tick()) * timeStretch,
172173
sigmap()->timesig(tick).nominal(), measure, MAX_DOTS, timeStretch);
173174
if (dl.empty()) {
174175
LOGD("Could not make durations for: %d/%d", len.numerator(), len.denominator());
175176
return;
176177
}
177178
TDuration d = dl[0];
178-
Fraction c2Tick(tick + c->tick());
179179
c2->setDurationType(d);
180180
c2->setTicks(d.fraction());
181-
rest -= c2->actualTicksAt(c2Tick);
182181
undoAddCR(c2, measure, tick);
183182

184183
std::vector<Note*> nl1 = c->notes();
@@ -201,9 +200,10 @@ void Score::pasteChordRest(ChordRest* cr, const Fraction& t)
201200
nl2[i]->setTieBack(tie);
202201
}
203202
}
204-
c = c2;
203+
rest -= c2->ticks();
204+
tick += c2->actualTicksAt(tick);
205205
firstpart = false;
206-
tick += c->actualTicksAt(c2Tick);
206+
c = c2;
207207
}
208208
} else if (cr->isRest()) {
209209
// split Rest
@@ -214,34 +214,35 @@ void Score::pasteChordRest(ChordRest* cr, const Fraction& t)
214214
while (!rest.isZero()) {
215215
Rest* r2 = firstpart ? r : toRest(r->clone());
216216
measure = tick2measure(tick);
217-
Fraction mlen = measure->endTick() - tick;
217+
Fraction timeStretch = stf->timeStretch(tick);
218+
Fraction mlen = (measure->endTick() - tick) * timeStretch;
218219
Fraction len = rest > mlen ? mlen : rest;
219-
Fraction timeStretch = r2->staff()->timeStretch(tick);
220-
std::vector<TDuration> dl = toRhythmicDurationList(len * timeStretch, true, (tick - measure->tick()) * timeStretch,
220+
std::vector<TDuration> dl = toRhythmicDurationList(len, true, (tick - measure->tick()) * timeStretch,
221221
sigmap()->timesig(tick).nominal(), measure, MAX_DOTS, timeStretch);
222222
if (dl.empty()) {
223223
LOGD("Could not make durations for: %d/%d", len.numerator(), len.denominator());
224224
return;
225225
}
226226
TDuration d = dl[0];
227227
r2->setDurationType(d);
228-
r2->setTicks(d.isMeasure() ? measure->ticks() : d.fraction());
228+
r2->setTicks(d.isMeasure() ? measure->stretchedLen(stf) : d.fraction());
229229
undoAddCR(r2, measure, tick);
230230
rest -= r2->ticks();
231231
tick += r2->actualTicksAt(tick);
232232
firstpart = false;
233233
}
234234
} else if (cr->isMeasureRepeat()) {
235235
MeasureRepeat* mr = toMeasureRepeat(cr);
236-
std::vector<TDuration> list = toDurationList(mr->actualTicks(), true);
236+
std::vector<TDuration> list = toDurationList(mr->ticks(), true);
237237
for (auto dur : list) {
238238
Rest* r = Factory::createRest(this->dummy()->segment(), dur);
239239
r->setTrack(cr->track());
240240
Fraction rest = r->ticks();
241241
while (!rest.isZero()) {
242242
Rest* r2 = toRest(r->clone());
243243
measure = tick2measure(tick);
244-
Fraction mlen = measure->endTick() - tick;
244+
Fraction timeStretch = stf->timeStretch(tick);
245+
Fraction mlen = (measure->endTick() - tick) * timeStretch;
245246
Fraction len = rest > mlen ? mlen : rest;
246247
std::vector<TDuration> dl = toDurationList(len, false);
247248
if (dl.empty()) {
@@ -252,7 +253,7 @@ void Score::pasteChordRest(ChordRest* cr, const Fraction& t)
252253
r2->setTicks(d.fraction());
253254
r2->setDurationType(d);
254255
undoAddCR(r2, measure, tick);
255-
rest -= d.fraction();
256+
rest -= r2->ticks();
256257
tick += r2->actualTicksAt(tick);
257258
}
258259
delete r;

src/engraving/editing/cmd.cpp

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1276,6 +1276,7 @@ Fraction Score::makeGap(Segment* segment, track_idx_t track, const Fraction& _sd
12761276
assert(_sd.numerator());
12771277

12781278
Measure* measure = segment->measure();
1279+
Staff* stf = staff(track2staff(track));
12791280
Fraction accumulated;
12801281
Fraction sd = _sd;
12811282

@@ -1292,13 +1293,15 @@ Fraction Score::makeGap(Segment* segment, track_idx_t track, const Fraction& _sd
12921293
// voices != 0 may have gaps:
12931294
//
12941295
ChordRest* cr = toChordRest(seg->element(track));
1296+
Fraction timeStretch = cr->staff()->timeStretch(cr->tick());
12951297
if (!cr) {
12961298
if (seg->tick() < nextTick) {
12971299
continue;
12981300
}
12991301
Segment* seg1 = seg->next(SegmentType::ChordRest);
13001302
Fraction tick2 = seg1 ? seg1->tick() : seg->measure()->endTick();
13011303
Fraction td(tick2 - seg->tick());
1304+
td *= timeStretch; // @reedbeta TODO - need to multiply by tuplet ratio also?
13021305
if (td > sd) {
13031306
td = sd;
13041307
}
@@ -1313,6 +1316,7 @@ Fraction Score::makeGap(Segment* segment, track_idx_t track, const Fraction& _sd
13131316
if (seg->tick() > nextTick) {
13141317
// there was a gap
13151318
Fraction td(seg->tick() - nextTick);
1319+
td *= timeStretch; // @reedbeta TODO - need to multiply by tuplet ratio also?
13161320
if (td > sd) {
13171321
td = sd;
13181322
}
@@ -1377,7 +1381,6 @@ Fraction Score::makeGap(Segment* segment, track_idx_t track, const Fraction& _sd
13771381
// even if there was a tuplet, we didn't remove it
13781382
ltuplet = 0;
13791383
}
1380-
Fraction timeStretch = cr->staff()->timeStretch(cr->tick());
13811384
nextTick += actualTicks(td, tuplet, timeStretch);
13821385
if (sd < td) {
13831386
//
@@ -1392,7 +1395,6 @@ Fraction Score::makeGap(Segment* segment, track_idx_t track, const Fraction& _sd
13921395
dList = toDurationList(rd, false);
13931396
std::reverse(dList.begin(), dList.end());
13941397
} else {
1395-
Staff* stf = staff(track2staff(track));
13961398
TimeSig* timeSig = stf->timeSig(tick);
13971399
TimeSigFrac refTimeSig = timeSig ? timeSig->sig() : sigmap()->timesig(tick).nominal();
13981400
Fraction rTickStart = (tick - measure->tick()) * stf->timeStretch(tick);
@@ -1419,19 +1421,9 @@ Fraction Score::makeGap(Segment* segment, track_idx_t track, const Fraction& _sd
14191421
break;
14201422
}
14211423
}
1422-
// Fraction ticks = measure->endTick() - segment->tick();
1423-
// Fraction td = Fraction::fromTicks(ticks);
1424-
// NEEDS REVIEW !!
1425-
// once the statement below is removed, these two lines do nothing
1426-
// if (td > sd)
1427-
// td = sd;
1428-
// ??? accumulated should already contain the total value of the created gap: line 749, 811 or 838
1429-
// this line creates a double-sized gap if the needed gap crosses a measure boundary
1430-
// by adding again the duration already added in line 838
1431-
// accumulated += td;
14321424

14331425
const Fraction t1 = firstSegmentEnd;
1434-
const Fraction t2 = firstSegment->tick() + accumulated;
1426+
const Fraction t2 = firstSegment->tick() + actualTicks(accumulated, tuplet, stf->timeStretch(firstSegment->tick()));
14351427
if (t1 < t2) {
14361428
Segment* s1 = tick2rightSegment(t1);
14371429
Segment* s2 = tick2rightSegment(t2);
@@ -1471,7 +1463,7 @@ bool Score::makeGap1(const Fraction& baseTick, staff_idx_t staffIdx, const Fract
14711463
if (!voiceOffset[track - strack].isValid()) {
14721464
continue;
14731465
}
1474-
Fraction tick = baseTick + voiceOffset[track - strack];
1466+
Fraction tick = baseTick + actualTicks(voiceOffset[track - strack], nullptr, staff(staffIdx)->timeStretch(baseTick));
14751467
Measure* tm = tick2measure(tick);
14761468
if ((track % VOICES) && !tm->hasVoices(staffIdx)) {
14771469
continue;
@@ -1481,7 +1473,7 @@ bool Score::makeGap1(const Fraction& baseTick, staff_idx_t staffIdx, const Fract
14811473
assert(newLen.numerator() != 0);
14821474

14831475
if (newLen > Fraction(0, 1)) {
1484-
const Fraction endTick = tick + newLen;
1476+
const Fraction endTick = tick + actualTicks(newLen, nullptr, staff(staffIdx)->timeStretch(tick));
14851477

14861478
SelectionFilter filter;
14871479
// chord symbols can exist without chord/rest so they should not be removed
@@ -1523,7 +1515,7 @@ bool Score::makeGapVoice(Segment* seg, track_idx_t track, Fraction len, const Fr
15231515
}
15241516
ChordRest* cr1 = toChordRest(seg1->element(track));
15251517
Fraction srcF = cr1->ticks();
1526-
Fraction dstF = tick - cr1->tick();
1518+
Fraction dstF = (tick - cr1->tick()) * cr1->staff()->timeStretch(cr1->tick());
15271519
std::vector<TDuration> dList = toDurationList(dstF, true);
15281520
if (dList.empty()) {
15291521
LOGD("Could not make durations for: %d/%d", dstF.numerator(), dstF.denominator());
@@ -4150,6 +4142,7 @@ void Score::cmdSlashRhythm()
41504142

41514143
//---------------------------------------------------------
41524144
// setChord
4145+
// 'dur' is in local (stretched) time
41534146
// return segment of last created chord
41544147
//---------------------------------------------------------
41554148
static Segment* setChord(Score* score, Segment* segment, track_idx_t track, const Chord* chordTemplate, Fraction dur)
@@ -4336,7 +4329,7 @@ void Score::cmdRealizeChordSymbols(bool literal, Voicing voicing, HDuration dura
43364329
const RealizedHarmony& r = h->getRealizedHarmony();
43374330
Segment* seg = h->explicitParent()->isSegment() ? toSegment(h->explicitParent()) : toSegment(h->explicitParent()->explicitParent());
43384331
Fraction tick = seg->tick();
4339-
Fraction duration = r.getActualDuration(tick.ticks(), durationType);
4332+
Fraction duration = r.getActualDuration(tick.ticks(), durationType) * h->staff()->timeStretch(tick);
43404333
bool concertPitch = style().styleB(Sid::concertPitch);
43414334

43424335
Chord* chord = Factory::createChord(this->dummy()->segment()); //chord template

src/engraving/editing/edit.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -450,7 +450,7 @@ ChordRest* Score::addClone(ChordRest* cr, const Fraction& tick, const TDuration&
450450
}
451451
newcr->mutldata()->setPosX(0.0);
452452
newcr->setDurationType(d);
453-
newcr->setTicks(d.isMeasure() ? cr->measure()->ticks() : d.fraction());
453+
newcr->setTicks(d.isMeasure() ? cr->measure()->stretchedLen(cr->staff()) : d.fraction());
454454
newcr->setTuplet(cr->tuplet());
455455
newcr->setSelected(false);
456456
if (newcr->isChord()) {
@@ -1824,19 +1824,19 @@ void Score::regroupNotesAndRests(const Fraction& startTick, const Fraction& endT
18241824
}
18251825
lastRest = cr;
18261826
}
1827-
Fraction restTicks = lastRest->tick() + lastRest->ticks() - curr->tick();
1827+
Fraction restTicks = (lastRest->endTick() - curr->tick()) * curr->staff()->timeStretch(curr->tick());
18281828
seg = setNoteRest(seg, curr->track(), NoteVal(), restTicks, DirectionV::AUTO, false, {}, true);
18291829
} else if (curr->isChord()) {
18301830
// combine tied chords
18311831
Chord* chord = toChord(curr);
18321832
Chord* lastTiedChord = chord;
1833-
for (Chord* next = chord->nextTiedChord(); next && next->tick() + next->ticks() <= maxTick; next = next->nextTiedChord()) {
1833+
for (Chord* next = chord->nextTiedChord(); next && next->endTick() <= maxTick; next = next->nextTiedChord()) {
18341834
lastTiedChord = next;
18351835
}
18361836
if (!lastTiedChord) {
18371837
lastTiedChord = chord;
18381838
}
1839-
Fraction noteTicks = lastTiedChord->tick() + lastTiedChord->ticks() - chord->tick();
1839+
Fraction noteTicks = (lastTiedChord->endTick() - chord->tick()) * chord->staff()->timeStretch(chord->tick());
18401840
if (!(curr->tuplet())) {
18411841
// store start/end note for backward/forward ties ending/starting on the group of notes being rewritten
18421842
size_t numNotes = chord->notes().size();

src/engraving/rw/read400/read400.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -427,9 +427,9 @@ bool Read400::pasteStaff(XmlReader& e, Segment* dst, staff_idx_t dstStaff, Fract
427427
}
428428
voice_idx_t voiceId = static_cast<voice_idx_t>(e.intAttribute("id", -1));
429429
assert(voiceId < VOICES);
430-
voiceOffset[voiceId] = Fraction::fromTicks(e.readInt());
430+
voiceOffset[voiceId] = Fraction::fromTicks(e.readInt()) * timeStretch;
431431
}
432-
if (!score->makeGap1(dstTick, dstStaffIdx, tickLen, voiceOffset)) {
432+
if (!score->makeGap1(dstTick, dstStaffIdx, tickLen * timeStretch, voiceOffset)) {
433433
LOGD() << "cannot make gap in staff " << dstStaffIdx << " at tick " << dstTick.ticks();
434434
done = true; // break main loop, cannot make gap
435435
break;
@@ -501,7 +501,7 @@ bool Read400::pasteStaff(XmlReader& e, Segment* dst, staff_idx_t dstStaff, Fract
501501
if (tuplet) {
502502
cr->readAddTuplet(tuplet);
503503
}
504-
ctx.incTick(cr->actualTicks());
504+
ctx.incTick(cr->actualTicksAt(tick));
505505
if (doScale) {
506506
Fraction d = cr->durationTypeTicks();
507507
cr->setTicks(cr->ticks() * scale);
@@ -521,7 +521,7 @@ bool Read400::pasteStaff(XmlReader& e, Segment* dst, staff_idx_t dstStaff, Fract
521521
Fraction d = t->durationType().ticks();
522522
t->setDurationType(d * scale);
523523
}
524-
Fraction tremoloEndTick = tick + chord->actualTicks();
524+
Fraction tremoloEndTick = tick + chord->actualTicksAt(tick);
525525
Fraction measureEndTick = score->tick2measure(tick)->endTick();
526526
if (tremoloEndTick > measureEndTick) {
527527
MScore::setError(MsError::DEST_TREMOLO);
@@ -542,7 +542,7 @@ bool Read400::pasteStaff(XmlReader& e, Segment* dst, staff_idx_t dstStaff, Fract
542542
graceNotes.clear();
543543
}
544544
// delete pending ties, they are not selected when copy
545-
if ((tick - dstTick) + cr->actualTicks() >= tickLen) {
545+
if ((tick - dstTick) + cr->actualTicksAt(tick) >= tickLen) {
546546
if (cr->isChord()) {
547547
Chord* c = toChord(cr);
548548
for (Note* note: c->notes()) {
@@ -555,7 +555,7 @@ bool Read400::pasteStaff(XmlReader& e, Segment* dst, staff_idx_t dstStaff, Fract
555555
}
556556
}
557557
// shorten last cr to fit in the space made by makeGap
558-
if ((tick - dstTick) + cr->actualTicks() > tickLen) {
558+
if ((tick - dstTick) + cr->actualTicksAt(tick) > tickLen) {
559559
Fraction newLength = tickLen - (tick - dstTick);
560560
// check previous CR on same track, if it has tremolo, delete the tremolo
561561
// we don't want a tremolo and two different chord durations
@@ -581,8 +581,8 @@ bool Read400::pasteStaff(XmlReader& e, Segment* dst, staff_idx_t dstStaff, Fract
581581
// shorten duration
582582
// exempt notes in tuplets, since we don't allow copy of partial tuplet anyhow
583583
// TODO: figure out a reasonable fudge factor to make sure shorten tuplets appropriately if we do ever copy a partial tuplet
584-
cr->setTicks(newLength);
585-
cr->setDurationType(newLength);
584+
cr->setTicks(newLength * timeStretch);
585+
cr->setDurationType(newLength * timeStretch);
586586
}
587587
}
588588
score->pasteChordRest(cr, tick);

0 commit comments

Comments
 (0)