📄 interpretcommand.cpp
字号:
double proportion = (double(e->getAbsoluteTime() - hairpinStartTime) / double(hairpinEndTime - hairpinStartTime)); long velocity = int((endingVelocity - startingVelocity) * proportion + startingVelocity); NOTATION_DEBUG << "InterpretCommand::applyHairpins: velocity of note at " << e->getAbsoluteTime() << " is " << velocity << " (" << proportion << " through hairpin from " << startingVelocity << " to " << endingVelocity << ")" << endl; if (velocity < 10) velocity = 10; if (velocity > 127) velocity = 127; e->set <Int>(VELOCITY, velocity); velocityToApply = velocity; }}voidInterpretCommand::stressBeats(){ Composition *c = getSegment().getComposition(); for (EventSelection::eventcontainer::iterator itr = m_selection->getSegmentEvents().begin(); itr != m_selection->getSegmentEvents().end(); ++itr) { Event *e = *itr; if (!e->isa(Note::EventType)) continue; timeT t = e->getNotationAbsoluteTime(); TimeSignature timeSig = c->getTimeSignatureAt(t); timeT barStart = getSegment().getBarStartForTime(t); int stress = timeSig.getEmphasisForTime(t - barStart); // stresses are from 0 to 4, so we add 12% to the velocity // at the maximum stress, subtract 4% at the minimum int velocityChange = stress * 4 - 4; // do this even if velocityChange == 0, in case the event // has no velocity yet long velocity = 100; e->get <Int>(VELOCITY, velocity); velocity += velocity * velocityChange / 100; if (velocity < 10) velocity = 10; if (velocity > 127) velocity = 127; e->set <Int>(VELOCITY, velocity); }}voidInterpretCommand::articulate(){ // Basic articulations: // // -- Anything marked tenuto or within a slur gets 100% of its // nominal duration (that's what we need the quantizer for, // to get the display nominal duration), and its velocity // is unchanged. // // -- Anything marked marcato gets 60%, or 70% if slurred (!), // and gets an extra 15% of velocity. // // -- Anything marked staccato gets 55%, or 70% if slurred, // and unchanged velocity. // // -- Anything marked staccatissimo gets 30%, or 50% if slurred (!), // and loses 5% of velocity. // // -- Anything marked sforzando gains 35% of velocity. // // -- Anything marked with an accent gains 30% of velocity. // // -- Anything marked rinforzando gains 15% of velocity and has // its full duration. Guess we really need to use some proper // controllers here. // // -- Anything marked down-bow gains 5% of velocity, anything // marked up-bow loses 5%. // // -- Anything unmarked and unslurred, or marked tenuto and // slurred, gets 90% of duration. std::set <Event *> toErase; std::set <Event *> toInsert; Segment &segment(getSegment()); for (EventSelection::eventcontainer::iterator ecitr = m_selection->getSegmentEvents().begin(); ecitr != m_selection->getSegmentEvents().end(); ++ecitr) { Event *e = *ecitr; if (!e->isa(Note::EventType)) continue; Segment::iterator itr = segment.findSingle(e); Chord chord(segment, itr, m_quantizer); // the things that affect duration bool staccato = false; bool staccatissimo = false; bool marcato = false; bool tenuto = false; bool rinforzando = false; bool slurred = false; int velocityChange = 0; std::vector<Mark> marks(chord.getMarksForChord()); for (std::vector<Mark>::iterator i = marks.begin(); i != marks.end(); ++i) { if (*i == Marks::Accent) { velocityChange += 30; } else if (*i == Marks::Tenuto) { tenuto = true; } else if (*i == Marks::Staccato) { staccato = true; } else if (*i == Marks::Staccatissimo) { staccatissimo = true; velocityChange -= 5; } else if (*i == Marks::Marcato) { marcato = true; velocityChange += 15; } else if (*i == Marks::Sforzando) { velocityChange += 35; } else if (*i == Marks::Rinforzando) { rinforzando = true; velocityChange += 15; } else if (*i == Marks::DownBow) { velocityChange += 5; } else if (*i == Marks::UpBow) { velocityChange -= 5; } } IndicationMap::iterator inditr = findEnclosingIndication(e, Indication::Slur); if (inditr != m_indications.end()) slurred = true; if (slurred) { // last note in a slur should be treated as if unslurred timeT slurEnd = inditr->first + inditr->second->getIndicationDuration(); if (slurEnd == e->getNotationAbsoluteTime() + e->getNotationDuration() || slurEnd == e->getAbsoluteTime() + e->getDuration()) { slurred = false; } /*!!! Segment::iterator slurEndItr = segment.findTime(slurEnd); if (slurEndItr != segment.end() && (*slurEndItr)->getNotationAbsoluteTime() <= e->getNotationAbsoluteTime()) { slurred = false; } */ } int durationChange = 0; if (slurred) { //!!! doesn't seem to be picking up slurs correctly if (tenuto) durationChange = -10; else if (marcato || staccato) durationChange = -30; else if (staccatissimo) durationChange = -50; else durationChange = 0; } else { if (tenuto) durationChange = 0; else if (marcato) durationChange = -40; else if (staccato) durationChange = -45; else if (staccatissimo) durationChange = -70; else if (rinforzando) durationChange = 0; else durationChange = -10; } NOTATION_DEBUG << "InterpretCommand::modifySegment: chord has " << chord.size() << " notes in it" << endl; for (Chord::iterator ci = chord.begin(); ci != chord.end(); ++ci) { e = **ci; NOTATION_DEBUG << "InterpretCommand::modifySegment: For note at " << e->getAbsoluteTime() << ", velocityChange is " << velocityChange << " and durationChange is " << durationChange << endl; // do this even if velocityChange == 0, in case the event // has no velocity yet long velocity = 100; e->get <Int>(VELOCITY, velocity); velocity += velocity * velocityChange / 100; if (velocity < 10) velocity = 10; if (velocity > 127) velocity = 127; e->set <Int>(VELOCITY, velocity); timeT duration = e->getNotationDuration(); // don't mess with the duration of a tied note bool tiedForward = false; if (e->get <Bool>(TIED_FORWARD, tiedForward) && tiedForward) { durationChange = 0; } timeT newDuration = duration + duration * durationChange / 100; // this comparison instead of "durationChange != 0" // because we want to permit the possibility of resetting // the performance duration of a note (that's perhaps been // articulated wrongly) based on the notation duration: if (e->getDuration() != newDuration) { if (toErase.find(e) == toErase.end()) { //!!! deal with tuplets Event *newEvent = new Event(*e, e->getAbsoluteTime(), newDuration, e->getSubOrdering(), e->getNotationAbsoluteTime(), duration); toInsert.insert(newEvent); toErase.insert(e); } } } // what we want to do here is jump our iterator to the final // element in the chord -- but that doesn't work because we're // iterating through the selection, not the segment. So for // now we just accept the fact that notes in chords might be // processed multiple times (slow) and added into the toErase // set more than once (hence the nasty tests in the loop just // after the close of this loop). } for (std::set <Event *>::iterator j = toErase.begin(); j != toErase.end(); ++j) { Segment::iterator jtr(segment.findSingle(*j)); if (jtr != segment.end()) segment.erase(jtr); } for (std::set <Event *>::iterator j = toInsert.begin(); j != toInsert.end(); ++j) { segment.insert(*j); }}InterpretCommand::IndicationMap::iteratorInterpretCommand::findEnclosingIndication(Event *e, std::string type){ // a bit slow, but let's wait and see whether it's a bottleneck // before we worry about that timeT t = e->getAbsoluteTime(); IndicationMap::iterator itr = m_indications.lower_bound(t); while (1) { if (itr != m_indications.end()) { if (itr->second->getIndicationType() == type && itr->first <= t && itr->first + itr->second->getIndicationDuration() > t) { return itr; } } if (itr == m_indications.begin()) break; --itr; } return m_indications.end();}}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -