File: importmidi_tuplet_tonotes.cpp

package info (click to toggle)
musescore2 2.3.2%2Bdfsg4-16
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 170,464 kB
  • sloc: cpp: 262,612; xml: 176,707; sh: 3,377; ansic: 1,246; python: 356; makefile: 227; perl: 82; pascal: 78
file content (121 lines) | stat: -rw-r--r-- 4,515 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#include "importmidi_tuplet_tonotes.h"
#include "importmidi_tuplet.h"
#include "importmidi_fraction.h"
#include "importmidi_inner.h"
#include "libmscore/staff.h"
#include "libmscore/score.h"
#include "libmscore/fraction.h"
#include "libmscore/duration.h"
#include "libmscore/measure.h"
#include "libmscore/tuplet.h"
#include "libmscore/mscore.h"
#include "libmscore/chordrest.h"


namespace Ms {
namespace MidiTuplet {

void addElementToTuplet(int voice,
                        const ReducedFraction &onTime,
                        const ReducedFraction &len,
                        DurationElement *el,
                        std::multimap<ReducedFraction, TupletData> &tuplets)
      {
      const auto foundTuplets = findTupletsForTimeRange(voice, onTime, len, tuplets, true);

#ifdef IMPORTMIDI_DEBUG
      if (foundTuplets.size() > 1) {
            qDebug() << "Measure number (from 1):" << el->measure()->no() + 1
                     << ", staff index (from 0):" << el->staff()->idx();

            Q_ASSERT_X(false, "MidiTuplet::addElementToTuplet",
                       "More than one tuplet contains specified duration");
            }
#endif

      if (!foundTuplets.empty()) {
            auto &tuplet = const_cast<TupletData &>(foundTuplets.front()->second);
            tuplet.elements.push_back(el);       // add chord/rest to the tuplet
            }
      }

void createTupletNotes(
            Staff *staff,
            const std::multimap<ReducedFraction, TupletData> &tuplets)
      {
      Score* score = staff->score();
      const int track = staff->idx() * VOICES;

      for (const auto &tupletEvent: tuplets) {
            const auto &tupletData = tupletEvent.second;
            if (tupletData.elements.empty())
                  continue;

            Tuplet* tuplet = new Tuplet(score);
            const auto &tupletRatio = tupletLimits(tupletData.tupletNumber).ratio;
            tuplet->setRatio(tupletRatio.fraction());

            tuplet->setDuration(tupletData.len.fraction());
            const TDuration baseLen = tupletData.len.fraction() / tupletRatio.denominator();
            tuplet->setBaseLen(baseLen);

            tuplet->setTrack(track);
            tuplet->setTick(tupletData.onTime.ticks());
            tuplet->setVoice(tupletData.voice);
            Measure* measure = score->tick2measure(tupletData.onTime.ticks());
            tuplet->setParent(measure);

            for (DurationElement *el: tupletData.elements) {
                  tuplet->add(el);
                  el->setTuplet(tuplet);
                  }
            }
      }


#ifdef IMPORTMIDI_DEBUG

void printInvalidTupletLocation(int measureIndex, int staffIndex)
      {
      qDebug() << "Tuplet is invalid; measure number (from 1):"
               << measureIndex + 1
               << ", staff index (from 0):" << staffIndex;
      }

bool haveTupletsEnoughElements(const Staff *staff)
      {
      const int strack = staff->idx() * VOICES;

      for (int voice = 0; voice < VOICES; ++voice) {
            for (Segment *seg = staff->score()->firstSegment(); seg; seg = seg->next1()) {
                  if (seg->segmentType() == Segment::Type::ChordRest) {
                        const ChordRest *cr = static_cast<ChordRest *>(seg->element(strack + voice));
                        if (!cr)
                              continue;
                        const Tuplet *tuplet = cr->tuplet();
                        if (tuplet) {
                              if (tuplet->elements().size() <= 1) {
                                    printInvalidTupletLocation(seg->measure()->no(), staff->idx());
                                    return false;
                                    }
                              int chordCount = 0;
                              for (const auto &e: tuplet->elements()) {
                                    const ChordRest *cr = static_cast<ChordRest *>(e);
                                    if (cr && cr->type() == Element::Type::CHORD)
                                          ++chordCount;
                                    }
                              if (chordCount == 0) {
                                    printInvalidTupletLocation(seg->measure()->no(), staff->idx());
                                    return false;
                                    }
                              }
                        }
                  }
            }
      return true;
      }

#endif

} // namespace MidiTuplet
} // namespace Ms