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