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()) { // grace before // try to tie to note in parent chord chord = toChord(chord->parent()); 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(Segment::Type::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; }
Note* Glissando::guessInitialNote(Chord* chord) { switch (chord->noteType()) { // case NoteType::INVALID: // return nullptr; // for grace notes before, previous chord is previous chord of parent chord case NoteType::ACCIACCATURA: case NoteType::APPOGGIATURA: case NoteType::GRACE4: case NoteType::GRACE16: case NoteType::GRACE32: // move unto parent chord and proceed to standard case if (chord->parent() && chord->parent()->type() == Element::Type::CHORD) chord = static_cast<Chord*>(chord->parent()); else return nullptr; break; // for grace notes after, return top note of parent chord case NoteType::GRACE8_AFTER: case NoteType::GRACE16_AFTER: case NoteType::GRACE32_AFTER: if (chord->parent() && chord->parent()->type() == Element::Type::CHORD) return static_cast<Chord*>(chord->parent())->upNote(); else // no parent or parent is not a chord? return nullptr; case NoteType::NORMAL: { // if chord has grace notes before, the last one is the previous note QVector<Chord*>graces = chord->graceNotesBefore(); if (graces.size() > 0) return graces.last()->upNote(); } break; // else process to standard case default: break; } // standard case (NORMAL or grace before chord) // if parent not a segment, can't locate a target note if (chord->parent()->type() != Element::Type::SEGMENT) return nullptr; int chordTrack = chord->track(); Segment* segm = chord->segment(); Part* part = chord->part(); if (segm != nullptr) segm = segm->prev1(); while (segm) { // if previous segment is a ChordRest segment if (segm->segmentType() == Segment::Type::ChordRest) { Chord* target = nullptr; // look for a Chord in the same track if (segm->element(chordTrack) && segm->element(chordTrack)->type() == Element::Type::CHORD) target = static_cast<Chord*>(segm->element(chordTrack)); else // if no same track, look for other chords in the same instrument for (Element* currChord : segm->elist()) if (currChord != nullptr && currChord->type() == Element::Type::CHORD && static_cast<Chord*>(currChord)->part() == part) { target = static_cast<Chord*>(currChord); break; } // if we found a target previous chord if (target) { // if chord has grace notes after, the last one is the previous note QVector<Chord*>graces = target->graceNotesAfter(); if (graces.size() > 0) return graces.last()->upNote(); return target->upNote(); // if no grace after, return top note } } segm = segm->prev1(); } qDebug("no first note for glissando found"); return nullptr; }