ChordRest* prevChordRest(ChordRest* cr) { if (!cr) return 0; if (cr->isGrace()) { // cr is a grace note Chord* c = static_cast<Chord*>(cr); Chord* pc = static_cast<Chord*>(cr->parent()); QList<Chord*> graceNotesBefore; QList<Chord*> graceNotesAfter; if(cr->isGraceBefore()){ pc->getGraceNotesBefore(&graceNotesBefore); auto i = std::find(graceNotesBefore.begin(),graceNotesBefore.end(), c); if (i == graceNotesBefore.end()) return 0; if (i == graceNotesBefore.begin()) cr = pc; else return *--i; } else { int n = pc->getGraceNotesAfter(&graceNotesAfter); for(int i = 0; i < n; i++){ if(c == graceNotesAfter[(i)]){ if(i > 0) return graceNotesAfter[i - 1]; else return 0; } } } } else { if (cr->type() == Element::CHORD) { Chord* c = static_cast<Chord*>(cr); if (!c->graceNotes().empty()) return c->graceNotes().back(); } } int track = cr->track(); Segment::SegmentTypes st = Segment::SegChordRest; for (Segment* seg = cr->segment()->prev1(st); seg; seg = seg->prev1(st)) { ChordRest* e = static_cast<ChordRest*>(seg->element(track)); if (e) return e; } return 0; }
void TestNote::grace() { Score* score = readScore(DIR + "grace.mscx"); score->doLayout(); Chord* chord = score->firstMeasure()->findChord(0, 0); Note* note = chord->upNote(); // create score->setGraceNote(chord, note->pitch(), NoteType::APPOGGIATURA, MScore::division/2); Chord* gc = chord->graceNotes().first(); Note* gn = gc->notes().first(); // Note* n = static_cast<Note*>(writeReadElement(gn)); // QCOMPARE(n->noteType(), NoteType::APPOGGIATURA); // delete n; // tie score->startCmd(); score->select(gn); score->cmdAddTie(); score->endCmd(); // n = static_cast<Note*>(writeReadElement(gn)); // QVERIFY(n->tieFor() != 0); // delete n; // tremolo score->startCmd(); Tremolo* tr = new Tremolo(score); tr->setTremoloType(TremoloType::R16); tr->setParent(gc); tr->setTrack(gc->track()); score->undoAddElement(tr); score->endCmd(); // Chord* c = static_cast<Chord*>(writeReadElement(gc)); // QVERIFY(c->tremolo() != 0); // delete c; // articulation score->startCmd(); Articulation* ar = new Articulation(score); ar->setArticulationType(ArticulationType::Sforzatoaccent); ar->setParent(gc); ar->setTrack(gc->track()); score->undoAddElement(ar); score->endCmd(); // c = static_cast<Chord*>(writeReadElement(gc)); // QVERIFY(c->articulations().size() == 1); // delete c; QVERIFY(saveCompareScore(score, "grace-test.mscx", DIR + "grace-ref.mscx")); }
Note* searchTieNote(Note* note) { Note* note2 = 0; Chord* chord = note->chord(); Segment* seg = chord->segment(); Part* part = chord->part(); int strack = part->staves()->front()->idx() * VOICES; int etrack = strack + part->staves()->size() * VOICES; if (chord->isGraceBefore()) { chord = toChord(chord->parent()); // try to tie to next grace note int index = chord->graceIndex(); for (Chord* c : chord->graceNotes()) { if (c->graceIndex() == index + 1) { note2 = c->findNote(note->pitch()); if (note2) { printf("found grace-grace tie\n"); return note2; } } } // try to tie to note in parent chord note2 = chord->findNote(note->pitch()); if (note2) return note2; } else if (chord->isGraceAfter()) { // grace after // we will try to tie to note in next normal chord, below // meanwhile, set chord to parent chord so the endTick calculation will make sense chord = toChord(chord->parent()); } else { // normal chord // try to tie to grace note after if present QVector<Chord*> gna = chord->graceNotesAfter(); if (!gna.empty()) { Chord* gc = gna[0]; note2 = gc->findNote(note->pitch()); if (note2) return note2; } } // at this point, chord is a regular chord, not a grace chord // and we are looking for a note in the *next* chord (grace or regular) // calculate end of current note duration // but err on the safe side in case there is roundoff in tick count int endTick = chord->tick() + chord->actualTicks() - 1; while ((seg = seg->next1(SegmentType::ChordRest))) { // skip ahead to end of current note duration as calculated above // but just in case, stop if we find element in current track if (seg->tick() < endTick && !seg->element(chord->track())) continue; for (int track = strack; track < etrack; ++track) { Element* e = seg->element(track); if (e == 0 || !e->isChord()) continue; Chord* c = toChord(e); // if there are grace notes before, try to tie to first one QVector<Chord*> gnb = c->graceNotesBefore(); if (!gnb.empty()) { Chord* gc = gnb[0]; Note* gn2 = gc->findNote(note->pitch()); if (gn2) return gn2; } int staffIdx = c->staffIdx() + c->staffMove(); if (staffIdx != chord->staffIdx() + chord->staffMove()) // cannot happen? continue; for (Note* n : c->notes()) { if (n->pitch() == note->pitch()) { if (note2 == 0 || c->track() == chord->track()) note2 = n; } } } if (note2) break; } return note2; }
ChordRest* nextChordRest(ChordRest* cr) { if (!cr) return 0; if (cr->isGrace()) { // // cr is a grace note Chord* c = static_cast<Chord*>(cr); Chord* pc = static_cast<Chord*>(cr->parent()); if (cr->isGraceBefore()) { QList<Chord*> graceNotesBefore; pc->getGraceNotesBefore(&graceNotesBefore); auto i = std::find(graceNotesBefore.begin(), graceNotesBefore.end(), c); if (i == graceNotesBefore.end()) return 0; // unable to find self? ++i; if (i != graceNotesBefore.end()) return *i; // if this was last grace note before, return parent return pc; } else { QList<Chord*> graceNotesAfter; pc->getGraceNotesAfter(&graceNotesAfter); auto i = std::find(graceNotesAfter.begin(), graceNotesAfter.end(), c); if (i == graceNotesAfter.end()) return 0; // unable to find self? ++i; if (i != graceNotesAfter.end()) return *i; // if this was last grace note after, fall through to find next main note cr = pc; } } else { // // cr is not a grace note if (cr->type() == Element::Type::CHORD) { Chord* c = static_cast<Chord*>(cr); if (!c->graceNotes().empty()) { QList<Chord*> graceNotesAfter; c->getGraceNotesAfter(&graceNotesAfter); if (!graceNotesAfter.isEmpty()) return graceNotesAfter.first(); } } } int track = cr->track(); Segment::Type st = Segment::Type::ChordRest; for (Segment* seg = cr->segment()->next1MM(st); seg; seg = seg->next1MM(st)) { ChordRest* e = static_cast<ChordRest*>(seg->element(track)); if (e) { if (e->type() == Element::Type::CHORD) { Chord* c = static_cast<Chord*>(e); if (!c->graceNotes().empty()) { QList<Chord*> graceNotesBefore; c->getGraceNotesBefore(&graceNotesBefore); if (!graceNotesBefore.isEmpty()) return graceNotesBefore.first(); } } return e; } } return 0; }