Exemplo n.º 1
0
void TscoreMeasure::checkBarLine() {
  if (duration() && m_free == 0) { // update bar line
      if (m_barLine->parentItem() != lastNote()->parentItem()) {
        m_barLine->setParentItem(lastNote());
        QPointF barLinePos = lastNote()->mapFromParent(QPointF(lastNote()->rightX() - 0.2, 0.0));
        m_barLine->setLine(barLinePos.x(), lastNote()->staff()->upperLinePos(), barLinePos.x(), lastNote()->staff()->upperLinePos() + 8.0);
        m_barLine->show();
      }
  } else if (m_free > 0) {
        m_barLine->hide();
  } else // TODO: It should never occur - delete it when tested
      qDebug() << debug() << "ARE YOU MAD? Measure has more notes than the meter allows!";
}
Exemplo n.º 2
0
void TscoreMeasure::fill() {
  QList<TscoreNote*> notesToShift;
  int remainDur = m_staff->shiftFromMeasure(id() + 1, m_free, notesToShift);
  qDebug() << debug() << "fill, remain" << remainDur << "to shift:" << notesToShift.count();
  for (int i = 0; i < notesToShift.size(); ++i) {
    m_notes.append(notesToShift[i]);
    connect(notesToShift[i], &TscoreNote::noteGoingToChange, this, &TscoreMeasure::noteChangedSlot);
  }
  if (remainDur) { // next measure has a part of a new note
      qDebug() << debug() << remainDur << "remained in the next measure";
      auto firstInNext = m_staff->measures()[id() + 1]->firstNote()->note();
      Tnote newNote(*firstInNext, Trhythm(remainDur, firstInNext->isRest()));
      auto inserted = m_staff->insertNote(newNote, lastNoteId() + 1, lastNote()->isReadOnly());
//       copyRhythmParams(inserted, firstInNext->rtm);
      fixStemDirection(inserted);
      insertNote(inserted->index() - firstNoteId(), inserted);
      m_staff->updateNotesPos();
      if (!inserted->note()->isRest()) // add a tie
        inserted->tieWithNext();
  } else {
      updateRhythmicGroups();
      resolveBeaming(0);
      checkBarLine();
  }

  content(this);
}
Exemplo n.º 3
0
void TscoreMeasure::addNewNote(Tnote& newNote) {
// prepare tie, if any to restore it after new note will be created
  auto lastN = lastNote();
  auto lastTie = lastN->note()->rtm.tie(); // backup tie state to revert it after new note will be added

// create a new note on the staff
  auto inserted = m_staff->insertNote(lastN->index() + 1, newNote);
  fixStemDirection(lastNote());
  qDebug() << debug() << "creating new note after" << lastN->index() << lastN->note()->toText() << newNote.rtm.string();

  if (!newNote.isRest()) {
    lastN->tieWithNext();
    if (lastTie == Trhythm::e_tieCont || lastTie == Trhythm::e_tieStart)
      inserted->tieWithNext();
  }
}
Exemplo n.º 4
0
/**
 *  iterate through notes in backward order (right to left), take note by note to release required duration
 *  create a list from taken notes to send it to the next measure
 *  split the latest note (the most right one in the measure) if necessary
 *  half of the duration remains in current measure at the end tied with
 *  a new note that has to be created and push to the beginning of the next measure
 */
int TscoreMeasure::releaseAtEnd(int dur, QList<TscoreNote*>& notesToOut, Tnote& newNote, int endNote) {
  int noteNr = m_notes.count() - 1;
  while (noteNr >= endNote && dur > 0) {
      auto lastN = lastNote();
      int lastDur = lastN->note()->duration();
      if (lastDur > dur) { // last note is longer than required space - split it then create and move the rest of its duration to the next measure
          if (Trhythm(lastDur - dur).rhythm() == Trhythm::e_none) { // subtracting can't be solved by single note
            split(lastN);                                           // then split on two notes
            continue;                                               // and call while loop again
          }
          Trhythm oldRhythm(lastN->note()->rtm); // preserve tie and stem direction
          lastN->setRhythm(Trhythm(lastDur - dur, lastN->note()->isRest()));
          copyRhythmParams(lastN, oldRhythm);
//           lastN->note()->rtm.setStemDown(oldRhythm.stemDown());
//           if (oldRhythm.tie())
//             lastN->note()->rtm.setTie(Trhythm::e_tieCont);
          newNote = Tnote(*lastN->note(), Trhythm(dur, lastN->note()->isRest()));
//           newNote.rtm.setStemDown(oldRhythm.stemDown());
          lastDur = dur;
      } else { // last note is the same long or smaller than required space - so move it to the next measure
          notesToOut << m_notes.takeLast();
          disconnect(notesToOut.last(), &TscoreNote::noteGoingToChange, this, &TscoreMeasure::noteChangedSlot);
          auto b = notesToOut.last()->beam();
          if (b) {
            m_beams.removeOne(b);
            delete b;
          }
      }
      dur -= lastDur;
      m_free += lastDur; // note was taken out so there is more free space in the measure
  }

  return dur;
}
Exemplo n.º 5
0
void TscoreMeasure::setStaff(TscoreStaff* st) {
  m_staff = st;
  setParent(st);
  for (TscoreBeam* b : m_beams)
    b->changeStaff(st);

  if (st->firstMeasure() == this) { // this measure was the last and went at the beginning of the next staff
      auto first = firstNote();
      if (first->note()->rtm.tie() > Trhythm::e_tieStart) { // tie continues or ends on first note
        auto prev = first->prevNote();
        if (prev->tie())
          prev->tie()->checkStaves();

        else // TODO: delete if not occurs
          qDebug() << debug() << "first note has tie flag set but tie doesn't exists";
      }
  } else if (st->lastMeasure() == this) { // this measure was the first and went at the end of previous staff
      auto last = lastNote();
      if (last->tie())
        last->tie()->checkStaves();
  }
}
Exemplo n.º 6
0
//#################################################################################################
//###################              PROTECTED           ############################################
//#################################################################################################
void TscoreMeasure::noteChangedSlot(TscoreNote* sn) {
  Tnote newNote; // new note that has to be created when rhythm duration is split
  QList<TscoreNote*> notesToOut;

  if (sn->rhythmChanged()) {
    // TODO: if new duration of changed note is longer than whole measure duration - split it here and create new measure with single note
    //       - still we don't know new pitch
    int prevDur = sn->rhythm()->duration();
    int newDur = sn->note()->duration();
    int nextMeasDur = 0;
    qDebug() << debug() << "rhythm changed from" << sn->rhythm()->string() << "to" << sn->note()->rtm.string() << "free" << m_free;
    if (m_free - (newDur - prevDur) < 0) { // There is not enough space for this note with longer duration
      /** 1. Try to release measure (move notes after this @p sn one to the next measure) */
        int leftDur = releaseAtEnd(newDur - prevDur - m_free, notesToOut, newNote, sn->index() - firstNoteId() + 1);
        if (leftDur) {
          sn->moveNote(sn->note()->isRest() ? 0 : sn->newNotePos()); // update position of note head
          sn->staff()->updatePitch(sn->index()); // update Tnote according to new head position
      /** 2. There is still not enough space for new duration - splitting duration of this @p sn note to fill free space in this measure
        * and create part of that duration in the next one */
          nextMeasDur = newDur - (m_free + prevDur);
          Trhythm oldRhythm(sn->note()->rtm);
          Trhythm newRtmOfChanged(m_free + prevDur);
          if (newRtmOfChanged.rhythm() == Trhythm::e_none) {
      /** 3. Unfortunately remained free space in the measure can't be filled with single rhythm value  */
              qDebug() << debug() << "To fill measure with remaining duration need to split note of" << m_free + prevDur;
              TrhythmList solvedList;
              Trhythm::resolve(m_free + prevDur, solvedList);
              if (solvedList.size() == 2) {
                  solvedList.first().setRest(oldRhythm.isRest());
                  solvedList.last().setRest(oldRhythm.isRest());
                  sn->note()->rtm.setRhythm(solvedList.first().duration());
                  copyRhythmParams(sn, oldRhythm);
                  Tnote n2(*sn->note(), solvedList.last());
                  // TODO: common code with @p split
                  auto inserted = m_staff->insertNote(n2, sn->index() + 1, sn->isReadOnly());
                  fixStemDirection(inserted);
                  m_notes.insert(inserted->index() - firstNoteId(), inserted);
                  connect(inserted, &TscoreNote::noteGoingToChange, this, &TscoreMeasure::noteChangedSlot);
//                   inserted->setGroup(sn->group());
                  m_staff->updateNotesPos(inserted->index());
                  if (!sn->note()->isRest())
                    restoreTie(oldRhythm.tie(), sn);
              } else
                  qDebug() << debug() << "Can not resolve duration of" << m_free + prevDur;
          } else {
              sn->note()->rtm.setRhythm(newRtmOfChanged);
              copyRhythmParams(sn, oldRhythm);
          }
        }
        qDebug() << debug() << "RECALCULATED, remained" << nextMeasDur;
        updateRhythmicGroups();
        resolveBeaming(sn->rhythmGroup());
        checkBarLine();
        if (nextMeasDur) {
      /** 4. At the beginning of the next staff, create new note of the same pitch with remaining duration. */
          Trhythm nextMeasRtm(nextMeasDur);
          if (nextMeasRtm.rhythm() == Trhythm::e_none) {
              splitThenInsert(nextMeasDur, lastNoteId() + 1, *sn->note(), sn->isReadOnly());
          } else {
              auto nextMeasNote = m_staff->insertNote(lastNoteId() + 1, Tnote(*sn->note(), nextMeasRtm), sn->isReadOnly());
              fixStemDirection(nextMeasNote);
          }
          if (!sn->note()->isRest())
            lastNote()->tieWithNext();
        }
    } else if (newDur == prevDur) {
        if (sn->note()->isRest() != sn->rhythm()->isRest())
          qDebug() << debug() << "note" << sn->index() << "changed to/from rest";
        resolveBeaming(sn->rhythmGroup(), sn->rhythmGroup());
        checkBarLine();
    } else { // measure duration is less than meter - take notes from the next measure
        m_free += prevDur - newDur;
        qDebug() << debug() << "needs duration" << m_free;
        fill();
    }
  }

  shiftReleased(notesToOut, newNote);
}
Exemplo n.º 7
0
qreal TscoreMeasure::notesWidth() {
  if (!isEmpty())
    return lastNote()->rightX() - firstNote()->x();
  else
    return 0.0;
}
Exemplo n.º 8
0
void TscoreMeasure::insertNote(int id, TscoreNote* sn) {
//   qDebug() << debug() << sn->note()->rtm.xmlType() << "inserting id" << id << "count" << m_notes.count() << "free" << m_free;
  int noteDur = sn->note()->duration();
  int resolveAfter = 0; // un-resolvable duration of new note

  QList<TscoreNote*> notesToOut;
  Tnote newNote; // new note that has to be created when rhythm duration is split

  if (sn->note()->rhythm() != Trhythm::e_none && m_free - noteDur < 0) { // move notes to the next measure if not enough space
    int toRelease = releaseAtEnd(noteDur - m_free, notesToOut, newNote, id);
    if (toRelease > 0) { // There is still not enough space
      if (m_free > 0) { // measure has some free space for the new note but not for entire
          if (Trhythm(m_free).rhythm() == Trhythm::e_none) {
              Trhythm subRhythm(noteDur - m_free, sn->note()->isRest());
              subRhythm.setTie(sn->note()->rtm.tie());
              subRhythm.setStemDown(sn->note()->rtm.stemDown());
              if (subRhythm.rhythm() == Trhythm::e_none)
                qDebug() << debug() << "can not shrink note to duration" << noteDur - m_free;
              sn->setRhythm(subRhythm);
              splitThenInsert(m_free, id, *sn->note(), sn->isReadOnly());
              insertNote(lastNoteId() + 1, sn);
              if (!sn->note()->isRest())
                lastNote()->tieWithNext();
              return;
          }
          Trhythm oldRhythm(sn->note()->rtm);
          sn->setRhythm(Trhythm(m_free, sn->note()->isRest()));
          copyRhythmParams(sn, oldRhythm);
//           sn->note()->rtm.setTie(oldRhythm.tie());
//           sn->note()->rtm.setStemDown(oldRhythm.stemDown());
          if (newNote.rhythm() != Trhythm::e_none) // TODO: remove when tested
            qDebug() << "NEW NOTE is already created!!!";
          Trhythm newRtm(noteDur - m_free, sn->note()->isRest());
          if (newRtm.rhythm() == Trhythm::e_none) // two notes have to be added
            resolveAfter = noteDur - m_free; // do it after
          else
            newNote = Tnote(*sn->note(), newRtm);
          noteDur = m_free;
      } else { // measure has not at all space
          qDebug() << debug() << "move entire note" << sn->note()->toText();
          notesToOut << sn;
          m_staff->shiftToMeasure(m_staff->measures().indexOf(this) + 1, notesToOut);
          return;
      }
    }
  }

  m_free -= noteDur;
  m_notes.insert(id, sn);

  qDebug() << debug() << "measure got a note" << sn->note()->rtm.xmlType() << "FREE" << m_free << "out" << notesToOut.count();
  connect(sn, &TscoreNote::noteGoingToChange, this, &TscoreMeasure::noteChangedSlot);

  updateRhythmicGroups();
  resolveBeaming(sn->rhythmGroup());
  checkBarLine();

  shiftReleased(notesToOut, newNote);
  if (resolveAfter) {
    auto lastN = lastNote();
    splitThenInsert(resolveAfter, lastN->index() + 1, *lastN->note(), lastN->isReadOnly());
  }

  content(this);
}
Exemplo n.º 9
0
void NoteList::reset()
{
  while (anyNotesPressed())
    deleteNote(lastNote());
}