1 //=============================================================================
2 // MuseScore
3 // Music Composition & Notation
4 //
5 // Copyright (C) 2002-2011 Werner Schweer
6 //
7 // This program is free software; you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License version 2
9 // as published by the Free Software Foundation and appearing in
10 // the file LICENCE.GPL
11 //=============================================================================
12
13 #include "durationtype.h"
14 #include "mscore.h"
15 #include "note.h"
16 #include "sig.h"
17 #include "measure.h"
18
19 namespace Ms {
20
21 //---------------------------------------------------------
22 // dots
23 //---------------------------------------------------------
24
getDots(int base,int rest,char * dots)25 static int getDots(int base, int rest, char* dots)
26 {
27 if (base < 16)
28 return rest;
29 *dots = 0;
30 if (rest >= base / 2) {
31 *dots = *dots + 1;
32 rest -= base / 2;
33 }
34 if (rest >= base / 4) {
35 *dots = *dots + 1;
36 rest -= base / 4;
37 }
38 if (rest >= base / 8) {
39 *dots = *dots + 1;
40 rest -= base / 8;
41 }
42 if (rest >= base / 16) {
43 *dots = *dots + 1;
44 rest -= base / 16;
45 }
46 if (*dots > MAX_DOTS)
47 *dots = MAX_DOTS;
48 return rest;
49 }
50
51 //---------------------------------------------------------
52 // setDots
53 //---------------------------------------------------------
54
setDots(int v)55 void TDuration::setDots(int v)
56 {
57 if (v > MAX_DOTS)
58 v = MAX_DOTS;
59 if (v < 0)
60 v = 0;
61 _dots = v;
62 }
63
64 //---------------------------------------------------------
65 // setVal
66 //---------------------------------------------------------
67
setVal(int ticks)68 void TDuration::setVal(int ticks)
69 {
70 if (ticks == 0)
71 _val = DurationType::V_MEASURE;
72 else {
73 TDuration dt;
74 for (int i = 0; i < int(TDuration::DurationType::V_ZERO); ++i) {
75 dt.setType(TDuration::DurationType(i));
76 int t = dt.ticks().ticks();
77 if (ticks / t) {
78 int remain = ticks % t;
79 const int SMALLEST_DOT_DIVISOR = 1 << MAX_DOTS;
80 if ((t - remain) < (t/SMALLEST_DOT_DIVISOR)) {
81 _val = DurationType(i - 1);
82 return;
83 }
84 _val = DurationType(i);
85 getDots(t, remain, &_dots);
86 return;
87 }
88 }
89 qDebug("2: no duration type for ticks %d", ticks);
90 _val = DurationType::V_QUARTER; // fallback default value
91 }
92 }
93
94 //---------------------------------------------------------
95 // ticks
96 //---------------------------------------------------------
97
ticks() const98 Fraction TDuration::ticks() const
99 {
100 Fraction t;
101 switch(_val) {
102 case DurationType::V_QUARTER: t = Fraction(1, 4); break;
103 case DurationType::V_1024TH: t = Fraction(1, 1024); break;
104 case DurationType::V_512TH: t = Fraction(1, 512); break;
105 case DurationType::V_256TH: t = Fraction(1, 256); break;
106 case DurationType::V_128TH: t = Fraction(1, 128); break;
107 case DurationType::V_64TH: t = Fraction(1, 64); break;
108 case DurationType::V_32ND: t = Fraction(1, 32); break;
109 case DurationType::V_16TH: t = Fraction(1, 16); break;
110 case DurationType::V_EIGHTH: t = Fraction(1, 8); break;
111 case DurationType::V_HALF: t = Fraction(1, 2); break;
112 case DurationType::V_WHOLE: t = Fraction(1, 1); break;
113 case DurationType::V_BREVE: t = Fraction(2, 1); break;
114 case DurationType::V_LONG: t = Fraction(4, 1); break;
115 case DurationType::V_ZERO:
116 case DurationType::V_MEASURE:
117 return Fraction(0,1);
118 default:
119 case DurationType::V_INVALID:
120 return Fraction(-1,1);
121 }
122 Fraction tmp = t;
123 for (int i = 0; i < _dots; ++i) {
124 tmp *= Fraction(1,2);
125 t += tmp;
126 }
127 return t;
128 }
129
130 //---------------------------------------------------------
131 // name
132 //---------------------------------------------------------
133
name() const134 QString TDuration::name() const
135 {
136 switch(_val) {
137 case DurationType::V_QUARTER: return "quarter";
138 case DurationType::V_EIGHTH: return "eighth";
139 case DurationType::V_1024TH: return "1024th";
140 case DurationType::V_512TH: return "512th";
141 case DurationType::V_256TH: return "256th";
142 case DurationType::V_128TH: return "128th";
143 case DurationType::V_64TH: return "64th";
144 case DurationType::V_32ND: return "32nd";
145 case DurationType::V_16TH: return "16th";
146 case DurationType::V_HALF: return "half";
147 case DurationType::V_WHOLE: return "whole";
148 case DurationType::V_MEASURE: return "measure";
149 case DurationType::V_BREVE: return "breve";
150 case DurationType::V_LONG: return "long";
151 default:
152 qDebug("TDuration::name(): invalid duration type %d", static_cast<int>(_val));
153 // fall through
154 case DurationType::V_ZERO:
155 case DurationType::V_INVALID: return "";
156 }
157 }
158
159 //---------------------------------------------------------
160 // headType
161 //---------------------------------------------------------
162
headType() const163 NoteHead::Type TDuration::headType() const
164 {
165 NoteHead::Type headType = NoteHead::Type::HEAD_WHOLE;
166 switch(_val) {
167 case DurationType::V_1024TH:
168 case DurationType::V_512TH:
169 case DurationType::V_256TH:
170 case DurationType::V_128TH:
171 case DurationType::V_64TH:
172 case DurationType::V_32ND:
173 case DurationType::V_16TH:
174 case DurationType::V_EIGHTH:
175 case DurationType::V_QUARTER:
176 headType = NoteHead::Type::HEAD_QUARTER;
177 break;
178 case DurationType::V_HALF:
179 headType = NoteHead::Type::HEAD_HALF;
180 break;
181 case DurationType::V_MEASURE:
182 case DurationType::V_WHOLE:
183 headType = NoteHead::Type::HEAD_WHOLE;
184 break;
185 case DurationType::V_BREVE:
186 headType = NoteHead::Type::HEAD_BREVIS;
187 break;
188 case DurationType::V_LONG:
189 headType = NoteHead::Type::HEAD_BREVIS;
190 break;
191 default:
192 case DurationType::V_INVALID:
193 case DurationType::V_ZERO:
194 headType = NoteHead::Type::HEAD_QUARTER;
195 break;
196 }
197 return headType;
198 }
199
200 //---------------------------------------------------------
201 // hooks
202 //---------------------------------------------------------
203
hooks() const204 int TDuration::hooks() const
205 {
206 static const int table[] = {
207 // V_LONG, V_BREVE, V_WHOLE, V_HALF, V_QUARTER, V_EIGHTH, V_16TH,
208 0, 0, 0, 0, 0, 1, 2,
209 // V_32ND, V_64TH, V_128TH, V_256TH, V_512TH, V_1024TH,
210 3, 4, 5, 6, 7, 8,
211 // V_ZERO, V_MEASURE, V_INVALID
212 0, 0, 0
213 };
214 return table[int(_val)];
215 }
216
217 //---------------------------------------------------------
218 // hasStem
219 //---------------------------------------------------------
220
hasStem() const221 bool TDuration::hasStem() const
222 {
223 switch(_val) {
224 case DurationType::V_1024TH:
225 case DurationType::V_512TH:
226 case DurationType::V_256TH:
227 case DurationType::V_128TH:
228 case DurationType::V_64TH:
229 case DurationType::V_32ND:
230 case DurationType::V_16TH:
231 case DurationType::V_EIGHTH:
232 case DurationType::V_QUARTER:
233 case DurationType::V_HALF:
234 case DurationType::V_LONG:
235 return true;
236 default:
237 return false;
238 }
239 }
240
241 //---------------------------------------------------------
242 // setVal
243 //---------------------------------------------------------
244
TDuration(const QString & s)245 TDuration::TDuration(const QString& s)
246 {
247 setType(s);
248 _dots = 0;
249 }
250
251 //---------------------------------------------------------
252 // setType
253 //---------------------------------------------------------
254
setType(const QString & s)255 void TDuration::setType(const QString& s)
256 {
257 if (s == "quarter")
258 _val = DurationType::V_QUARTER;
259 else if (s == "eighth")
260 _val = DurationType::V_EIGHTH;
261 else if (s == "1024th")
262 _val = DurationType::V_1024TH;
263 else if (s == "512th")
264 _val = DurationType::V_512TH;
265 else if (s == "256th")
266 _val = DurationType::V_256TH;
267 else if (s == "128th")
268 _val = DurationType::V_128TH;
269 else if (s == "64th")
270 _val = DurationType::V_64TH;
271 else if (s == "32nd")
272 _val = DurationType::V_32ND;
273 else if (s == "16th")
274 _val = DurationType::V_16TH;
275 else if (s == "half")
276 _val = DurationType::V_HALF;
277 else if (s == "whole")
278 _val = DurationType::V_WHOLE;
279 else if (s == "breve")
280 _val = DurationType::V_BREVE;
281 else if (s == "long")
282 _val = DurationType::V_LONG;
283 else if (s == "measure")
284 _val = DurationType::V_MEASURE;
285 else {
286 // _val = V_INVALID;
287 _val = DurationType::V_QUARTER;
288 qDebug("TDuration::setType(%s): unknown, assume \"quarter\"", qPrintable(s));
289 }
290 }
291
292 //---------------------------------------------------------
293 // shiftType
294 // If stepDotted = false, duration type will inc/dec by
295 // nSteps with _dots remaining same.
296 //
297 // If stepDotted = true, duration will round toward zero
298 // to next single-dotted or undotted duration and then
299 // will included dotted durations when stepping
300 //---------------------------------------------------------
301
shiftType(int nSteps,bool stepDotted)302 void TDuration::shiftType(int nSteps, bool stepDotted)
303 {
304 if (_val == DurationType::V_MEASURE || _val == DurationType::V_INVALID || _val == DurationType::V_ZERO)
305 setType(DurationType::V_INVALID);
306 else {
307 int newValue;
308 int newDots;
309 if (stepDotted) {
310 // figure out the new duration in terms of the number of single dotted or undotted steps from DurationType::V_LONG
311 int roundDownSingleDots = (_dots > 0) ? -1 : 0;
312 int newValAsNumSingleDotSteps = int(_val) * 2 + roundDownSingleDots + nSteps;
313
314 // convert that new duration back into terms of DurationType integer value and number of dots
315 newDots = newValAsNumSingleDotSteps % 2; // odd means there is a dot
316 newValue = newValAsNumSingleDotSteps / 2 + newDots; // if new duration has a dot, then that
317 }
318 else {
319 newDots = _dots;
320 newValue = int(_val) + nSteps;
321 }
322
323 if ((newValue < int(DurationType::V_LONG)) || (newValue > int(DurationType::V_1024TH)) ||
324 ((newValue >= int(DurationType::V_1024TH)) && (newDots >= 1)) ||
325 ((newValue >= int(DurationType::V_512TH)) && (newDots >= 2)) ||
326 ((newValue >= int(DurationType::V_256TH)) && (newDots >= 3)) ||
327 ((newValue >= int(DurationType::V_128TH)) && (newDots >= 4)))
328 setType(DurationType::V_INVALID);
329 else {
330 setType(DurationType(newValue));
331 setDots(newDots);
332 }
333 }
334 }
335
336 //---------------------------------------------------------
337 // operator<
338 //---------------------------------------------------------
339
operator <(const TDuration & t) const340 bool TDuration::operator<(const TDuration& t) const
341 {
342 if (t._val < _val)
343 return true;
344 if (t._val == _val) {
345 if (_dots < t._dots)
346 return true;
347 }
348 return false;
349 }
350
351 //---------------------------------------------------------
352 // operator>=
353 //---------------------------------------------------------
354
operator >=(const TDuration & t) const355 bool TDuration::operator>=(const TDuration& t) const
356 {
357 if (t._val > _val)
358 return true;
359 if (t._val == _val) {
360 if (_dots >= t._dots)
361 return true;
362 }
363 return false;
364 }
365
366 //---------------------------------------------------------
367 // operator<=
368 //---------------------------------------------------------
369
operator <=(const TDuration & t) const370 bool TDuration::operator<=(const TDuration& t) const
371 {
372 if (t._val < _val)
373 return true;
374 if (t._val == _val) {
375 if (_dots <= t._dots)
376 return true;
377 }
378 return false;
379 }
380
381 //---------------------------------------------------------
382 // operator>
383 //---------------------------------------------------------
384
operator >(const TDuration & t) const385 bool TDuration::operator>(const TDuration& t) const
386 {
387 if (t._val > _val)
388 return true;
389 if (t._val == _val) {
390 if (_dots > t._dots)
391 return true;
392 }
393 return false;
394 }
395
396 //---------------------------------------------------------
397 // fraction
398 //---------------------------------------------------------
399
fraction() const400 Fraction TDuration::fraction() const
401 {
402 int z = 1;
403 unsigned n;
404 switch(_val) {
405 case DurationType::V_1024TH: n = 1024; break;
406 case DurationType::V_512TH: n = 512; break;
407 case DurationType::V_256TH: n = 256; break;
408 case DurationType::V_128TH: n = 128; break;
409 case DurationType::V_64TH: n = 64; break;
410 case DurationType::V_32ND: n = 32; break;
411 case DurationType::V_16TH: n = 16; break;
412 case DurationType::V_EIGHTH: n = 8; break;
413 case DurationType::V_QUARTER: n = 4; break;
414 case DurationType::V_HALF: n = 2; break;
415 case DurationType::V_WHOLE: n = 1; break;
416 case DurationType::V_BREVE: z = 2; n = 1; break;
417 case DurationType::V_LONG: z = 4; n = 1; break;
418 case DurationType::V_ZERO: z = 0; n = 1; break;
419 default: z = 0; n = 0; break; // zero+invalid fraction
420 }
421
422 //dots multiplier is (2^(n + 1) - 1)/(2^n) where n is the number of dots
423 int dotN = (1 << (_dots + 1)) - 1;
424 int dotD = 1 << _dots;
425
426 return Fraction(z * dotN, n * dotD);
427 }
428
429 // Longest TDuration that fits into Fraction. Must fit exactly if truncate = false.
TDuration(const Fraction & l,bool truncate,int maxDots,DurationType maxType)430 TDuration::TDuration(const Fraction& l, bool truncate, int maxDots, DurationType maxType)
431 {
432 #ifdef NDEBUG
433 Q_UNUSED(truncate);
434 #endif
435 setType(maxType); // use maxType to avoid testing all types if you know that l is smaller than a certain DurationType
436 setDots(maxDots);
437 truncateToFraction(l, maxDots);
438 Q_ASSERT(truncate || (fraction() - l).numerator() == 0); // check for exact fit
439 }
440
441 //---------------------------------------------------------
442 // truncateToFraction
443 //---------------------------------------------------------
444
truncateToFraction(const Fraction & l,int maxDots)445 void TDuration::truncateToFraction(const Fraction& l, int maxDots)
446 {
447 // try to fit in l by reducing number of duration dots
448 if (setDotsToFitFraction(l, _dots))
449 return;
450
451 // that wasn't enough so now change type too
452 for (shiftType(1); isValid(); shiftType(1)) {
453 if (setDotsToFitFraction(l, maxDots))
454 return; // duration fits fits in l
455 }
456
457 }
458
459 //---------------------------------------------------------
460 // setDotsToFitFraction
461 //---------------------------------------------------------
462
setDotsToFitFraction(const Fraction & l,int maxDots)463 bool TDuration::setDotsToFitFraction(const Fraction& l, int maxDots)
464 {
465 for ( ; maxDots >= 0; maxDots--) {
466 _dots = maxDots; // ensures _dots >= 0 if function returns false.
467 if ((fraction() - l).numerator() <= 0)
468 return true; // duration fits in l
469 }
470
471 return false; // doesn't fit by changing dots alone (type needs to be changed too)
472 }
473
474 //---------------------------------------------------------
475 // operator -=
476 //---------------------------------------------------------
477
operator -=(const TDuration & t)478 TDuration& TDuration::operator-=(const TDuration& t)
479 {
480 Fraction f1 = fraction() - t.fraction();
481 TDuration d(f1);
482 _val = d._val;
483 _dots = d._dots;
484 return *this;
485 }
486
487 //---------------------------------------------------------
488 // operator +=
489 //---------------------------------------------------------
490
operator +=(const TDuration & t)491 TDuration& TDuration::operator+=(const TDuration& t)
492 {
493 Fraction f1 = fraction() + t.fraction();
494 TDuration d(f1);
495 _val = d._val;
496 _dots = d._dots;
497 return *this;
498 }
499
500 //---------------------------------------------------------
501 // toDurationList
502 //---------------------------------------------------------
503
toDurationList(Fraction l,bool useDots,int maxDots,bool printRestRemains)504 std::vector<TDuration> toDurationList(Fraction l, bool useDots, int maxDots, bool printRestRemains)
505 {
506 std::vector<TDuration> dList;
507 dList.reserve(8);
508
509 if (!useDots)
510 maxDots = 0;
511
512 for (TDuration dd(l, true, maxDots); dd.isValid() && l.numerator() > 0; dd = TDuration(l, true, maxDots, dd.type())) {
513 dList.push_back(dd);
514 l -= dd.fraction();
515 }
516
517 if (printRestRemains && l.numerator() != 0)
518 qDebug("toDurationList:: rest remains %d/%d", l.numerator(), l.denominator());
519
520 return dList;
521 }
522
523 //---------------------------------------------------------
524 // toRhythmicDurationList
525 //---------------------------------------------------------
526
toRhythmicDurationList(const Fraction & l,bool isRest,Fraction rtickStart,const TimeSigFrac & nominal,Measure * msr,int maxDots)527 std::vector<TDuration> toRhythmicDurationList(const Fraction& l, bool isRest, Fraction rtickStart, const TimeSigFrac& nominal, Measure* msr, int maxDots)
528 {
529 std::vector<TDuration> dList;
530 dList.reserve(8);
531
532 if (msr->isAnacrusis())
533 rtickStart = Fraction::fromTicks(nominal.ticksPerMeasure()) - rtickStart;
534 else if (isRest && l == msr->ticks()) {
535 TDuration d = TDuration(TDuration::DurationType::V_MEASURE);
536 dList.push_back(d);
537 return dList;
538 }
539
540 if (nominal.isCompound())
541 splitCompoundBeatsForList(&dList, l, isRest, rtickStart, nominal, maxDots);
542 else
543 populateRhythmicList(&dList, l, isRest, rtickStart, nominal, maxDots);
544
545 return dList;
546 }
547
548 //---------------------------------------------------------
549 // populateRhythmicList
550 //---------------------------------------------------------
551
populateRhythmicList(std::vector<TDuration> * dList,const Fraction & l,bool isRest,const Fraction & rtickStart,const TimeSigFrac & nominal,int maxDots)552 void populateRhythmicList(std::vector<TDuration>* dList, const Fraction& l, bool isRest, const Fraction& rtickStart, const TimeSigFrac& nominal, int maxDots)
553 {
554 Fraction rtickEnd = rtickStart + l;
555
556 bool needToSplit = false; // do we need to split?
557 int rtickSplit = 0; // tick to split on if we need to
558
559 // CHECK AT SUBBEAT LEVEL
560
561 int startLevel = nominal.rtick2subbeatLevel(rtickStart.ticks());
562 int endLevel = nominal.rtick2subbeatLevel(rtickEnd.ticks());
563 int strongestLevelCrossed = nominal.strongestSubbeatLevelInRange(rtickStart.ticks(), rtickEnd.ticks(), &rtickSplit); // sets rtickSplit
564
565 if ((startLevel < 0) || (endLevel < 0) || (strongestLevelCrossed < 0)) {
566 // Beyond maximum subbeat level so just split into largest possible durations.
567 std::vector<TDuration> dList2 = toDurationList(l, maxDots > 0, maxDots, false);
568 dList->insert(dList->end(), dList2.begin(), dList2.end());
569 return;
570 }
571
572 // split if we cross something stronger than where we start and end
573 if ((strongestLevelCrossed < startLevel) && (strongestLevelCrossed < endLevel))
574 needToSplit = true;
575 // but don't split for level 1 syncopation (allow eight-note, quarter, quarter... to cross unstressed beats)
576 if (startLevel == endLevel && strongestLevelCrossed == startLevel - 1)
577 needToSplit = false;
578 // nor for the next simplest case of level 2 syncopation (allow sixteenth-note, eighth, eighth... to cross unstressed beats)
579 if (startLevel == endLevel && strongestLevelCrossed == startLevel - 2) {
580 // but disallow sixteenth-note, quarter, quarter...
581 int ticksToNext = nominal.ticksToNextSubbeat(rtickStart.ticks(), startLevel - 1);
582 int ticksPastPrev = nominal.ticksPastSubbeat(rtickStart.ticks(), startLevel - 1);
583 needToSplit = ticksToNext != ticksPastPrev;
584 }
585
586 if (!needToSplit && strongestLevelCrossed == 0) {
587 // NOW CHECK AT DENOMINATOR UNIT LEVEL AND BEAT LEVEL
588 BeatType startBeat = nominal.rtick2beatType(rtickStart.ticks());
589 BeatType endBeat = nominal.rtick2beatType(rtickEnd.ticks());
590
591 int dUnitsCrossed = 0; // number of timeSig denominator units the note/rest crosses
592 // if there is a choice of which beat to split on, should we use the first or last?
593 bool useLast = startBeat <= BeatType::SIMPLE_UNSTRESSED; // split on the later beat if starting on a beat
594
595 BeatType strongestBeatCrossed = nominal.strongestBeatInRange(rtickStart.ticks(), rtickEnd.ticks(), &dUnitsCrossed, &rtickSplit, useLast);
596
597 needToSplit = forceRhythmicSplit(isRest, startBeat, endBeat, dUnitsCrossed, strongestBeatCrossed, nominal);
598 }
599
600 if (!needToSplit) {
601 // CHECK THERE IS A DURATION THAT FITS
602 // crossed beats/subbeats were not important so try to avoid splitting
603 TDuration d = TDuration(l, true, maxDots);
604 if (d.fraction() == l) {
605 // we can use a single duration - no need to split!
606 dList->push_back(l);
607 return;
608 }
609 // no single TDuration fits so must split anyway
610 }
611
612 // Split on the strongest beat or subbeat crossed
613 Fraction leftSplit = Fraction::fromTicks(rtickSplit) - rtickStart;
614 Fraction rightSplit = l - leftSplit;
615
616 // Recurse to see if we need to split further before adding to list
617 populateRhythmicList(dList, leftSplit, isRest, rtickStart, nominal, maxDots);
618 populateRhythmicList(dList, rightSplit, isRest, Fraction::fromTicks(rtickSplit) , nominal, maxDots);
619 }
620
621 //---------------------------------------------------------
622 // splitCompoundBeatsForList
623 // Split compound notes/rests where they enter a compound beat.
624 //---------------------------------------------------------
625
splitCompoundBeatsForList(std::vector<TDuration> * dList,const Fraction & l,bool isRest,const Fraction & rtickStart,const TimeSigFrac & nominal,int maxDots)626 void splitCompoundBeatsForList(std::vector<TDuration>* dList, const Fraction& l, bool isRest,
627 const Fraction& rtickStart, const TimeSigFrac& nominal, int maxDots)
628 {
629 Fraction rtickEnd = rtickStart + l;
630
631 BeatType startBeat = nominal.rtick2beatType(rtickStart.ticks());
632 BeatType endBeat = nominal.rtick2beatType(rtickEnd.ticks());
633
634 if (startBeat > BeatType::COMPOUND_UNSTRESSED) {
635 // Not starting on a compound beat so mustn't extend into next compound beat
636 int splitTicks = nominal.ticksToNextBeat(rtickStart.ticks());
637
638 if ((rtickEnd - rtickStart).ticks() > splitTicks) {
639 // Duration extends into next beat so must split
640 Fraction leftSplit = Fraction::fromTicks(splitTicks);
641 Fraction rightSplit = l - leftSplit;
642 populateRhythmicList(dList, leftSplit, isRest, rtickStart, nominal, maxDots); // this side is ok to proceed
643 splitCompoundBeatsForList(dList, rightSplit, isRest, rtickStart + Fraction::fromTicks(splitTicks), nominal, maxDots); // not checked yet
644 return;
645 }
646 }
647
648 if (endBeat > BeatType::COMPOUND_UNSTRESSED) {
649 // Not ending on a compound beat so mustn't extend into previous compound beat
650 int splitTicks = nominal.ticksPastBeat(rtickEnd.ticks());
651
652 if ((rtickEnd - rtickStart).ticks() > splitTicks) {
653 // Duration extends into previous beat so must split
654 Fraction rightSplit = Fraction::fromTicks(splitTicks);
655 Fraction leftSplit = l - rightSplit;
656 populateRhythmicList(dList, leftSplit, isRest, rtickStart, nominal, maxDots); // must add leftSplit to list first
657 populateRhythmicList(dList, rightSplit, isRest, rtickEnd - Fraction::fromTicks(splitTicks), nominal, maxDots);
658 return;
659 }
660 }
661
662 // Duration either starts and ends on compound beats, or it remains within a single compound beat
663 populateRhythmicList(dList, l, isRest, rtickStart, nominal, maxDots);
664 }
665
666 //---------------------------------------------------------
667 // forceRhythmicSplit
668 // Where to split notes and force a tie to indicate rhythm.
669 //
670 // The function assumes the following:
671 // * Note/rest has already been split at measure boundaries.
672 // * Full measure rest was used if possible
673 // * Note/rest already split where it enters a compound beat.
674 //
675 // Usage: Set crossedBeat to the strongest BeatType crossed by
676 // the note. Split note if function returns true. Repeat with
677 // the two new notes, and so on, until function returns false.
678 //
679 // Note: If no single TDuration can fill the gap then the note
680 // *has* to be split, regardless of what this function returns.
681 // Non-rhythmic splits should still occur on the strongest beat.
682 //
683 // Implementation: When comparing BeatTypes use <, <=, >, >=
684 // instead of == and != as appropriate (see sig.h). E.g. to match
685 // all full beats: "<= SIMPLE_UNSTRESSED". This will match for
686 // all compound and simple full beats, and not any subbeats.
687 //---------------------------------------------------------
688
forceRhythmicSplit(bool isRest,BeatType startBeat,BeatType endBeat,int dUnitsCrossed,BeatType strongestBeatCrossed,const TimeSigFrac & nominal)689 bool forceRhythmicSplit(bool isRest, BeatType startBeat, BeatType endBeat,
690 int dUnitsCrossed, BeatType strongestBeatCrossed, const TimeSigFrac& nominal) {
691
692 // Assumption: Notes were split at measure boundary before this function was
693 // called. (Necessary because timeSig might be different in next measure.)
694 Q_ASSERT(strongestBeatCrossed != BeatType::DOWNBEAT);
695 // Assumption: compound notes have already been split where they enter a compound beat.
696 // (Necessary because the split beat is not always the strongest beat in this case.)
697 Q_ASSERT(!nominal.isCompound() || strongestBeatCrossed >= BeatType::COMPOUND_SUBBEAT
698 || (startBeat <= BeatType::COMPOUND_UNSTRESSED && endBeat <= BeatType::COMPOUND_UNSTRESSED));
699
700 // SPECIAL CASES
701
702 // nothing can cross a stressed beat in an irregular time signature
703 if (strongestBeatCrossed <= BeatType::SIMPLE_STRESSED && !nominal.isTriple() && !nominal.isDuple())
704 return true;
705 if (isRest) {
706 // rests must not cross the middle of a bar with numerator == 2 (e.g. 2/4 bar) even though the beat is unstressed
707 if (strongestBeatCrossed <= BeatType::SIMPLE_UNSTRESSED && nominal.numerator() == 2)
708 return true;
709 // rests must not cross a beat in a triple meter - simple (e.g. 3/4) or compound (e.g. 9/8)
710 if (strongestBeatCrossed <= BeatType::SIMPLE_UNSTRESSED && nominal.isTriple())
711 return true;
712 }
713
714 // GENERAL RULES
715
716 if (nominal.isCompound())
717 return forceRhythmicSplitCompound(isRest, startBeat, endBeat, dUnitsCrossed, strongestBeatCrossed);
718 else
719 return forceRhythmicSplitSimple(isRest, startBeat, endBeat, dUnitsCrossed, strongestBeatCrossed);
720 }
721
722 //---------------------------------------------------------
723 // forceRhythmicSplitCompound
724 //---------------------------------------------------------
725
forceRhythmicSplitCompound(bool isRest,BeatType startBeat,BeatType endBeat,int dUnitsCrossed,BeatType strongestBeatCrossed)726 bool forceRhythmicSplitCompound(bool isRest, BeatType startBeat, BeatType endBeat, int dUnitsCrossed, BeatType strongestBeatCrossed)
727 {
728 switch (strongestBeatCrossed) {
729 case BeatType::COMPOUND_STRESSED:
730 // Assumption: compound notes have already been split where they enter a compound beat.
731 Q_ASSERT(startBeat <= BeatType::COMPOUND_UNSTRESSED && endBeat <= BeatType::COMPOUND_UNSTRESSED);
732 // Notes are guaranteed to and start on a compound beat so we can pretend we have a simple measure.
733 return forceRhythmicSplitSimple(isRest, startBeat, endBeat, dUnitsCrossed / 3, BeatType::SIMPLE_STRESSED);
734 case BeatType::COMPOUND_UNSTRESSED:
735 // Same assumption as before
736 Q_ASSERT(startBeat <= BeatType::COMPOUND_UNSTRESSED && endBeat <= BeatType::COMPOUND_UNSTRESSED);
737 // No further conditions since note are guaranteed to start and end on a compound beat.
738 return false;
739 case BeatType::COMPOUND_SUBBEAT:
740 // don't split anything that takes up a full compound beat
741 if (startBeat <= BeatType::COMPOUND_UNSTRESSED && endBeat <= BeatType::COMPOUND_UNSTRESSED)
742 return false;
743 // split rests that don't start on a compound beat
744 if (isRest && startBeat > BeatType::COMPOUND_UNSTRESSED)
745 return true;
746 // Remaining groupings within compound triplets are the same as for simple triple (3/4, 3/8, etc.)
747 return forceRhythmicSplitSimple(isRest, startBeat, endBeat, dUnitsCrossed, BeatType::SIMPLE_UNSTRESSED);
748 default: // BeatType::SUBBEAT
749 return forceRhythmicSplitSimple(isRest, startBeat, endBeat, dUnitsCrossed, strongestBeatCrossed);
750 }
751 }
752
753 //---------------------------------------------------------
754 // forceRhythmicSplitSimple
755 // Implementation: This function is also called for compound
756 // measures so be careful when comparing BeatTypes. Use <, <=,
757 // >, >= instead of == and != when appropriate. (See sig.h)
758 //---------------------------------------------------------
759
forceRhythmicSplitSimple(bool isRest,BeatType startBeat,BeatType endBeat,int beatsCrossed,BeatType strongestBeatCrossed)760 bool forceRhythmicSplitSimple(bool isRest, BeatType startBeat, BeatType endBeat, int beatsCrossed, BeatType strongestBeatCrossed)
761 {
762 switch (strongestBeatCrossed) {
763 case BeatType::SIMPLE_STRESSED:
764 // Must split rests on a stressed beat.
765 if (isRest)
766 return true;
767 // Don't split notes that start or end on a stressed beat. Enables double-dotting in 4/4.
768 // (Don't remove this to disable double-dotting, instead set maxDots = 1 elsewhere.)
769 if (startBeat <= BeatType::SIMPLE_STRESSED || endBeat <= BeatType::SIMPLE_STRESSED)
770 return false;
771 // Don't split notes that both start and end on unstressed beats or stronger.
772 if (startBeat <= BeatType::SIMPLE_UNSTRESSED && endBeat <= BeatType::SIMPLE_UNSTRESSED)
773 return false;
774 // anything else must split on stressed beat.
775 return true;
776 case BeatType::SIMPLE_UNSTRESSED:
777 // Don't split notes or rests if starting and ending on stressed beat.
778 if (startBeat <= BeatType::SIMPLE_STRESSED && endBeat <= BeatType::SIMPLE_STRESSED)
779 return false;
780 // Split rests that don't start or end on a beat. Notes may cross 1 unstressed beat.
781 if (startBeat == BeatType::SUBBEAT || endBeat == BeatType::SUBBEAT)
782 return isRest || (beatsCrossed > 1);
783 return false;
784 default: // BeatType::SUBBEAT
785 return false;
786 }
787 }
788
789 //---------------------------------------------------------
790 // print
791 //---------------------------------------------------------
792
durationTypeUserName() const793 QString TDuration::durationTypeUserName() const
794 {
795 QString s = QObject::tr("Custom");
796 switch(_val) {
797 case DurationType::V_LONG: s = QObject::tr("Longa" ); break;
798 case DurationType::V_BREVE: s = QObject::tr("Breve" ); break;
799 case DurationType::V_WHOLE: s = QObject::tr("Whole" ); break;
800 case DurationType::V_HALF: s = QObject::tr("Half" ); break;
801 case DurationType::V_QUARTER: s = QObject::tr("Quarter"); break;
802 case DurationType::V_EIGHTH: s = QObject::tr("Eighth" ); break;
803 case DurationType::V_16TH: s = QObject::tr("16th" ); break;
804 case DurationType::V_32ND: s = QObject::tr("32nd" ); break;
805 case DurationType::V_64TH: s = QObject::tr("64th" ); break;
806 case DurationType::V_128TH: s = QObject::tr("128th" ); break;
807 case DurationType::V_256TH: s = QObject::tr("256th" ); break;
808 case DurationType::V_512TH: s = QObject::tr("512th" ); break;
809 case DurationType::V_1024TH: s = QObject::tr("1024th" ); break;
810 case DurationType::V_ZERO: s = QObject::tr("Zero" ); break;
811 case DurationType::V_MEASURE: s = QObject::tr("Measure"); break;
812 case DurationType::V_INVALID: s = QObject::tr("Invalid"); break;
813 };
814 return s;
815 }
816
817 //---------------------------------------------------------
818 // setType
819 //---------------------------------------------------------
820
setType(DurationType t)821 void TDuration::setType(DurationType t)
822 {
823 _val = t;
824 if (_val == DurationType::V_MEASURE)
825 _dots = 0;
826 }
827
828 //---------------------------------------------------------
829 // isValid
830 //---------------------------------------------------------
831
isValid(Fraction f)832 bool TDuration::isValid(Fraction f)
833 {
834 TDuration t;
835 t.setType(DurationType::V_LONG);
836 t.setDots(4);
837 t.truncateToFraction(f, 4);
838 return (t.isValid() && (t.fraction() - f).numerator() == 0);
839 }
840 }
841
842