Exemplo n.º 1
0
Note* Glissando::guessFinalNote(Chord* chord)
      {
      int         chordTrack  = chord->track();
      Segment*    segm        = chord->segment();
      Part*       part        = chord->staff()->part();
      if (segm != nullptr)
            segm = segm->next1();
      while (segm) {
            // if next segment is a ChordRest segment
            if (segm->segmentType() == Segment::Type::ChordRest) {
                  // look for a Chord in the same track and returns its top note, if found
                  if (segm->element(chordTrack) && segm->element(chordTrack)->type() == Element::Type::CHORD)
                        return static_cast<Chord*>(segm->element(chordTrack))->upNote();
                  // if no chord, 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)->staff()->part() == part)
                              return static_cast<Chord*>(currChord)->upNote();
                  }
            segm = segm->next1();
            }
      qDebug("no second note for glissando found");
      return nullptr;
      }
Exemplo n.º 2
0
Note* Glissando::guessFinalNote(Chord* chord)
      {
      switch (chord->noteType()) {
//            case NoteType::INVALID:
//                  return nullptr;
            // for grace notes before, return top note of parent chord
            // TODO : if the grace-before is not the LAST ONE, this still returns the main note
            //    which is probably not correct; however a glissando between two grace notes
            //    probably makes little sense.
            case NoteType::ACCIACCATURA:
            case NoteType::APPOGGIATURA:
            case NoteType::GRACE4:
            case NoteType::GRACE16:
            case NoteType::GRACE32:
                  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;
            // for grace notes after, next chord is next chord of parent chord
            // TODO : same note as case above!
            case NoteType::GRACE8_AFTER:
            case NoteType::GRACE16_AFTER:
            case NoteType::GRACE32_AFTER:
                  // 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;
            case NoteType::NORMAL:
                  {
                  // if chord has grace notes after, the first one is the next note
                  QVector<Chord*>graces = chord->graceNotesAfter();
                  if (graces.size() > 0)
                        return graces.first()->upNote();
                  }
                  break;
            default:
                  break;
            }

      // standard case (NORMAL or grace after chord)

      // if parent not a segment, can't locate a target note
      if (chord->parent()->type() != Element::Type::SEGMENT)
            return nullptr;

      // look for first ChordRest segment after initial note is elapsed
      Segment*    segm        = chord->score()->tick2rightSegment(chord->tick() + chord->actualTicks());
      int         chordTrack  = chord->track();
      Part*       part        = chord->part();
      while (segm) {
            // if next 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 next chord
                  if (target) {
                        // if chord has grace notes before, the first one is the next note
                        QVector<Chord*>graces = target->graceNotesBefore();
                        if (graces.size() > 0)
                              return graces.first()->upNote();
                        return target->upNote();      // if no grace before, return top note
                        }
                  }
            segm = segm->next1();
            }
      qDebug("no second note for glissando found");
      return nullptr;
      }
Exemplo n.º 3
0
void StringData::fretChords(Chord * chord) const
      {
      int   nFret, nNewFret, nTempFret;
      int   nString, nNewString, nTempString;

      if(bFretting)
            return;
      bFretting = true;

      // we need to keep track of each string we allocate ourselves within this algorithm
      bool bUsed[strings()];                    // initially all strings are available
      for(nString=0; nString<strings(); nString++)
            bUsed[nString] = false;
      // we also need the notes sorted in order of string (from highest to lowest) and then pitch
      QMap<int, Note *> sortedNotes;
      int   count = 0;
      // if chord parent is not a segment, the chord is special (usually a grace chord):
      // fret it by itself, ignoring the segment
      if (chord->parent()->type() != Element::Type::SEGMENT)
            sortChordNotes(sortedNotes, chord, &count);
      else {
            // scan each chord of seg from same staff as 'chord', inserting each of its notes in sortedNotes
            Segment* seg = chord->segment();
            int trk;
            int trkFrom = (chord->track() / VOICES) * VOICES;
            int trkTo   = trkFrom + VOICES;
            for(trk = trkFrom; trk < trkTo; ++trk) {
                  Element* ch = seg->elist().at(trk);
                  if (ch && ch->type() == Element::Type::CHORD)
                        sortChordNotes(sortedNotes, static_cast<Chord*>(ch), &count);
                  }
            }

      // scan chord notes from highest, matching with strings from the highest
      foreach(Note * note, sortedNotes) {
            nString     = nNewString    = note->string();
            nFret       = nNewFret      = note->fret();
            note->setFretConflict(false);       // assume no conflicts on this note
            // if no fretting yet or current fretting is no longer valid
            if (nString == STRING_NONE || nFret == FRET_NONE || getPitch(nString, nFret) != note->pitch()) {
                  // get a new fretting
                  if(!convertPitch(note->pitch(), &nNewString, &nNewFret) ) {
                        // no way to fit this note in this tab:
                        // mark as fretting conflict
                        note->setFretConflict(true);
                        // store fretting change without affecting chord context
                        if (nFret != nNewFret)
                              note->score()->undoChangeProperty(note, P_ID::FRET, nNewFret);
                        if (nString != nNewString)
                              note->score()->undoChangeProperty(note, P_ID::STRING, nNewString);
                        continue;
                        }

                  // check this note is not using the same string of another note of this chord
                  foreach(Note * note2, sortedNotes) {
                        // if same string...
                        if(note2 != note && note2->string() == nNewString) {
                              // ...attempt to fret this note on its old string
                              if( (nTempFret=fret(note->pitch(), nString)) != FRET_NONE) {
                                    nNewFret   = nTempFret;
                                    nNewString = nString;
                                    }
                              break;
                              }
                        }
                  }

            // check we are not reusing a string we already used
            if(bUsed[nNewString]) {
                  // ...try with each other string, from the highest
                  for(nTempString=0; nTempString < strings(); nTempString++) {
                        if(bUsed[nTempString])
                              continue;
                        if( (nTempFret=fret(note->pitch(), nTempString)) != FRET_NONE) {
                              // suitable string found
                              nNewFret    = nTempFret;
                              nNewString  = nTempString;
                              break;
                              }
                        }
                  // if we run out of strings
                  if(nTempString >= strings()) {
                        // no way to fit this chord in this tab:
                        // mark this note as fretting conflict
                        note->setFretConflict(true);
//                        continue;
                        }
                  }

            // if fretting did change, store as a fret change
            if (nFret != nNewFret)
                  note->score()->undoChangeProperty(note, P_ID::FRET, nNewFret);
            if (nString != nNewString)
                  note->score()->undoChangeProperty(note, P_ID::STRING, nNewString);

            bUsed[nNewString] = true;           // string is used
            }
Exemplo n.º 4
0
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;
      }
Exemplo n.º 5
0
void StringData::fretChords(Chord * chord) const
      {
      int   nFret, minFret, maxFret, nNewFret, nTempFret;
      int   nString, nNewString, nTempString;

      if(bFretting)
            return;
      bFretting = true;

      // we need to keep track of string allocation
      int bUsed[strings()];                    // initially all strings are available
      for(nString=0; nString<strings(); nString++)
            bUsed[nString] = 0;
      // we also need the notes sorted in order of string (from highest to lowest) and then pitch
      QMap<int, Note *> sortedNotes;
      int   count = 0;
      // store staff pitch offset at this tick, to speed up actual note pitch calculations
      // (ottavas not implemented yet)
      int transp = chord->staff() ? chord->part()->instrument()->transpose().chromatic : 0;     // TODO: tick?
      int pitchOffset = /*chord->staff()->pitchOffset(chord->segment()->tick())*/ - transp;
      // if chord parent is not a segment, the chord is special (usually a grace chord):
      // fret it by itself, ignoring the segment
      if (chord->parent()->type() != ElementType::SEGMENT)
            sortChordNotes(sortedNotes, chord, pitchOffset, &count);
      else {
            // scan each chord of seg from same staff as 'chord', inserting each of its notes in sortedNotes
            Segment* seg = chord->segment();
            int trk;
            int trkFrom = (chord->track() / VOICES) * VOICES;
            int trkTo   = trkFrom + VOICES;
            for(trk = trkFrom; trk < trkTo; ++trk) {
                  Element* ch = seg->elist().at(trk);
                  if (ch && ch->type() == ElementType::CHORD)
                        sortChordNotes(sortedNotes, toChord(ch), pitchOffset, &count);
                  }
            }
      // determine used range of frets
      minFret = INT32_MAX;
      maxFret = INT32_MIN;
      foreach(Note* note, sortedNotes) {
            if (note->string() != STRING_NONE)
                  bUsed[note->string()]++;
            if (note->fret() != FRET_NONE && note->fret() < minFret)
                  minFret = note->fret();
            if (note->fret() != FRET_NONE && note->fret() > maxFret)
                  maxFret = note->fret();
      }

      // scan chord notes from highest, matching with strings from the highest
      foreach(Note * note, sortedNotes) {
            nString     = nNewString    = note->string();
            nFret       = nNewFret      = note->fret();
            note->setFretConflict(false);       // assume no conflicts on this note
            // if no fretting (any invalid fretting has been erased by sortChordNotes() )
            if (nString == STRING_NONE /*|| nFret == FRET_NONE || getPitch(nString, nFret) != note->pitch()*/) {
                  // get a new fretting
                  if (!convertPitch(note->pitch(), pitchOffset, &nNewString, &nNewFret) ) {
                        // no way to fit this note in this tab:
                        // mark as fretting conflict
                        note->setFretConflict(true);
                        // store fretting change without affecting chord context
                        if (nFret != nNewFret)
                              note->undoChangeProperty(Pid::FRET, nNewFret);
                        if (nString != nNewString)
                              note->undoChangeProperty(Pid::STRING, nNewString);
                        continue;
                        }
                  // note can be fretted: use string
                  else {
                        bUsed[nNewString]++;
                        }
                  }

            // if the note string (either original or newly assigned) is also used by another note
            if (bUsed[nNewString] > 1) {
                  // attempt to find a suitable string, from topmost
                  for (nTempString=0; nTempString < strings(); nTempString++) {
                        if (bUsed[nTempString] < 1
                                    && (nTempFret=fret(note->pitch(), nTempString, pitchOffset)) != FRET_NONE) {
                              bUsed[nNewString]--;    // free previous string
                              bUsed[nTempString]++;   // and occupy new string
                              nNewFret   = nTempFret;
                              nNewString = nTempString;
                              break;
                              }
                        }
                  }

            // TODO : try to optimize used fret range, avoiding eccessively open positions

            // if fretting did change, store as a fret change
            if (nFret != nNewFret)
                  note->undoChangeProperty(Pid::FRET, nNewFret);
            if (nString != nNewString)
                  note->undoChangeProperty(Pid::STRING, nNewString);
            }