// --------------------------------------------------------------------------- // fixPhaseBefore // //! Recompute phases of all Breakpoints earlier than the specified time //! so that the synthesize phases of those earlier Breakpoints matches //! the stored phase, and the synthesized phase at the specified //! time matches the stored (not recomputed) phase. //! //! Backward phase-fixing stops if a null (zero-amplitude) Breakpoint //! is encountered, because nulls are interpreted as phase reset points //! in Loris. If a null is encountered, the remainder of the Partial //! (the front part) is fixed in the forward direction, beginning at //! the start of the Partial. //! //! \param p The Partial whose phases should be fixed. //! \param t The time before which phases should be adjusted. // void fixPhaseBefore( Partial & p, double t ) { if ( 1 < p.numBreakpoints() ) { Partial::iterator pos = p.findNearest( t ); Assert( pos != p.end() ); fixPhaseBackward( p.begin(), pos ); } }
// --------------------------------------------------------------------------- // fixPhaseAfter // //! Recompute phases of all Breakpoints later than the specified time //! so that the synthesize phases of those later Breakpoints matches //! the stored phase, as long as the synthesized phase at the specified //! time matches the stored (not recomputed) phase. //! //! Phase fixing is only applied to non-null (nonzero-amplitude) Breakpoints, //! because null Breakpoints are interpreted as phase reset points in //! Loris. If a null is encountered, its phase is simply left unmodified, //! and future phases wil be recomputed from that one. //! //! \param p The Partial whose phases should be fixed. //! \param t The time after which phases should be adjusted. // void fixPhaseAfter( Partial & p, double t ) { // nothing to do it there are not at least // two Breakpoints in the Partial if ( 1 < p.numBreakpoints() ) { Partial::iterator pos = p.findNearest( t ); Assert( pos != p.end() ); fixPhaseForward( pos, --p.end() ); } }
// --------------------------------------------------------------------------- // fixPhaseBetween // //! Fix the phase travel between two times by adjusting the //! frequency and phase of Breakpoints between those two times. //! //! This algorithm assumes that there is nothing interesting about the //! phases of the intervening Breakpoints, and modifies their frequencies //! as little as possible to achieve the correct amount of phase travel //! such that the frequencies and phases at the specified times //! match the stored values. The phases of all the Breakpoints between //! the specified times are recomputed. //! //! THIS DOES NOT YET TREAT NULL BREAKPOINTS DIFFERENTLY FROM OTHERS. //! //! \pre There must be at least one Breakpoint in the //! Partial between the specified times tbeg and tend. //! \post The phases and frequencies of the Breakpoints in the //! range have been recomputed such that an oscillator //! initialized to the parameters of the first Breakpoint //! will arrive at the parameters of the last Breakpoint, //! and all the intervening Breakpoints will be matched. //! \param p The partial whose phases and frequencies will be recomputed. //! The Breakpoint at this position is unaltered. //! \param tbeg The phases and frequencies of Breakpoints later than the //! one nearest this time will be modified. //! \param tend The phases and frequencies of Breakpoints earlier than the //! one nearest this time will be modified. Should be greater //! than tbeg, or else they will be swapped. // void fixPhaseBetween( Partial & p, double tbeg, double tend ) { if ( tbeg > tend ) { std::swap( tbeg, tend ); } // for Partials that do not extend over the entire // specified time range, just recompute phases from // beginning or end of the range: if ( p.endTime() < tend ) { // OK if start time is also after tbeg, will // just recompute phases from start of p. fixPhaseAfter( p, tbeg ); } else if ( p.startTime() > tbeg ) { fixPhaseBefore( p, tend ); } else { // invariant: // p begins before tbeg and ends after tend. Partial::iterator b = p.findNearest( tbeg ); Partial::iterator e = p.findNearest( tend ); // if there is a null Breakpoint n between b and e, then // should fix forward from b to n, and backward from // e to n. Otherwise, do this complicated thing. Partial::iterator nullbp = std::find_if( b, e, BreakpointUtils::isNull ); if ( nullbp != e ) { fixPhaseForward( b, nullbp ); fixPhaseBackward( nullbp, e ); } else { fixPhaseBetween( b, e ); } } }
// --------------------------------------------------------------------------- // fixPhaseForward // //! Recompute phases of all Breakpoints later than the specified time //! so that the synthesize phases of those later Breakpoints matches //! the stored phase, as long as the synthesized phase at the specified //! time matches the stored (not recomputed) phase. Breakpoints later than //! tend are unmodified. //! //! Phase fixing is only applied to non-null (nonzero-amplitude) Breakpoints, //! because null Breakpoints are interpreted as phase reset points in //! Loris. If a null is encountered, its phase is simply left unmodified, //! and future phases wil be recomputed from that one. //! //! HEY Is this interesting, in general? Why would you want to do this? //! //! \param p The Partial whose phases should be fixed. //! \param tbeg The phases and frequencies of Breakpoints later than the //! one nearest this time will be modified. //! \param tend The phases and frequencies of Breakpoints earlier than the //! one nearest this time will be modified. Should be greater //! than tbeg, or else they will be swapped. // void fixPhaseForward( Partial & p, double tbeg, double tend ) { if ( tbeg > tend ) { std::swap( tbeg, tend ); } // nothing to do it there are not at least // two Breakpoints in the Partial if ( 1 < p.numBreakpoints() ) { // find the positions nearest tbeg and tend Partial::iterator posbeg = p.findNearest( tbeg ); Partial::iterator posend = p.findNearest( tend ); // if the positions are different, and tend is // the end, back it up if ( posbeg != posend && posend == p.end() ) { --posend; } fixPhaseForward( posbeg, posend ); } }