#ifndef INCLUDE_PARTIALUTILS_H #define INCLUDE_PARTIALUTILS_H /* * This is the Loris C++ Class Library, implementing analysis, * manipulation, and synthesis of digitized sounds using the Reassigned * Bandwidth-Enhanced Additive Sound Model. * * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY, without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * PartialUtils.h * * A group of Partial utility function objects for use with STL * searching and sorting algorithms. PartialUtils is a namespace * within the Loris namespace. * * This file defines three kinds of functors: * - Partial mutators * - predicates on Partials * - Partial comparitors * * Kelly Fitz, 6 July 2000 * loris@cerlsoundgroup.org * * http://www.cerlsoundgroup.org/Loris/ * */ #include "Envelope.h" #include "Partial.h" #include #include // begin namespace namespace Loris { namespace PartialUtils { // -- Partial mutating functors -- // --------------------------------------------------------------------------- // PartialMutator // //! PartialMutator is an abstract base class for Partial mutators, //! functors that operate on Partials according to a time-varying //! envelope. The base class manages a polymorphic Envelope instance //! that provides the time-varying mutation parameters. //! //! \invariant env is a non-zero pointer to a valid instance of a //! class derived from the abstract class Envelope. class PartialMutator : public std::unary_function< Partial, void > { public: //! Construct a new PartialMutator from a constant mutation factor. PartialMutator( double x ); //! Construct a new PartialMutator from an Envelope representing //! a time-varying mutation factor. PartialMutator( const Envelope & e ); //! Construct a new PartialMutator that is a copy of another. PartialMutator( const PartialMutator & rhs ); //! Destroy this PartialMutator, deleting its Envelope. virtual ~PartialMutator( void ); //! Make this PartialMutator a duplicate of another one. //! //! \param rhs is the PartialMutator to copy. PartialMutator & operator=( const PartialMutator & rhs ); //! Function call operator: apply a mutation factor to the //! specified Partial. Derived classes must implement this //! member. virtual void operator()( Partial & p ) const = 0; protected: //! pointer to an envelope that governs the //! time-varying mutation Envelope * env; }; // --------------------------------------------------------------------------- // AmplitudeScaler // //! Scale the amplitude of the specified Partial according to //! an envelope representing a time-varying amplitude scale value. // class AmplitudeScaler : public PartialMutator { public: //! Construct a new AmplitudeScaler from a constant scale factor. AmplitudeScaler( double x ) : PartialMutator( x ) {} //! Construct a new AmplitudeScaler from an Envelope representing //! a time-varying scale factor. AmplitudeScaler( const Envelope & e ) : PartialMutator( e ) {} //! Function call operator: apply a scale factor to the specified //! Partial. void operator()( Partial & p ) const; }; // --------------------------------------------------------------------------- // scaleAmplitude // --------------------------------------------------------------------------- //! Scale the amplitude of the specified Partial according to //! an envelope representing a amplitude scale value or envelope. //! //! \param p is a Partial to mutate. //! \param arg is either a constant scale factor or an Envelope //! describing the time-varying scale factor. // template< class Arg > void scaleAmplitude( Partial & p, const Arg & arg ) { AmplitudeScaler scaler( arg ); scaler( p ); } // --------------------------------------------------------------------------- // scaleAmplitude // --------------------------------------------------------------------------- //! Scale the amplitude of a sequence of Partials according to //! an envelope representing a amplitude scale value or envelope. //! //! \param b is the beginning of a sequence of Partials to mutate. //! \param e is the end of a sequence of Partials to mutate. //! \param arg is either a constant scale factor or an Envelope //! describing the time-varying scale factor. // template< class Iter, class Arg > void scaleAmplitude( Iter b, Iter e, const Arg & arg ) { AmplitudeScaler scaler( arg ); while ( b != e ) { scaler( *b++ ); } } // --------------------------------------------------------------------------- // BandwidthScaler // //! Scale the bandwidth of the specified Partial according to //! an envelope representing a time-varying bandwidth scale value. // class BandwidthScaler : public PartialMutator { public: //! Construct a new BandwidthScaler from a constant scale factor. BandwidthScaler( double x ) : PartialMutator( x ) {} //! Construct a new BandwidthScaler from an Envelope representing //! a time-varying scale factor. BandwidthScaler( const Envelope & e ) : PartialMutator( e ) {} //! Function call operator: apply a scale factor to the specified //! Partial. void operator()( Partial & p ) const; }; // --------------------------------------------------------------------------- // scaleBandwidth // --------------------------------------------------------------------------- //! Scale the bandwidth of the specified Partial according to //! an envelope representing a amplitude scale value or envelope. //! //! \param p is a Partial to mutate. //! \param arg is either a constant scale factor or an Envelope //! describing the time-varying scale factor. // template< class Arg > void scaleBandwidth( Partial & p, const Arg & arg ) { BandwidthScaler scaler( arg ); scaler( p ); } // --------------------------------------------------------------------------- // scaleBandwidth // --------------------------------------------------------------------------- //! Scale the bandwidth of a sequence of Partials according to //! an envelope representing a bandwidth scale value or envelope. //! //! \param b is the beginning of a sequence of Partials to mutate. //! \param e is the end of a sequence of Partials to mutate. //! \param arg is either a constant scale factor or an Envelope //! describing the time-varying scale factor. // template< class Iter, class Arg > void scaleBandwidth( Iter b, Iter e, const Arg & arg ) { BandwidthScaler scaler( arg ); while ( b != e ) { scaler( *b++ ); } } // --------------------------------------------------------------------------- // BandwidthSetter // //! Set the bandwidth of the specified Partial according to //! an envelope representing a time-varying bandwidth value. // class BandwidthSetter : public PartialMutator { public: //! Construct a new BandwidthSetter from a constant bw factor. BandwidthSetter( double x ) : PartialMutator( x ) {} //! Construct a new BandwidthSetter from an Envelope representing //! a time-varying bw factor. BandwidthSetter( const Envelope & e ) : PartialMutator( e ) {} //! Function call operator: assign a bw factor to the specified //! Partial. void operator()( Partial & p ) const; }; // --------------------------------------------------------------------------- // setBandwidth // --------------------------------------------------------------------------- //! Set the bandwidth of the specified Partial according to //! an envelope representing a amplitude scale value or envelope. //! //! \param p is a Partial to mutate. //! \param arg is either a constant scale factor or an Envelope //! describing the time-varying bw factor. // template< class Arg > void setBandwidth( Partial & p, const Arg & arg ) { BandwidthSetter setter( arg ); setter( p ); } // --------------------------------------------------------------------------- // setBandwidth // --------------------------------------------------------------------------- //! Set the bandwidth of a sequence of Partials according to //! an envelope representing a bandwidth value or envelope. //! //! \param b is the beginning of a sequence of Partials to mutate. //! \param e is the end of a sequence of Partials to mutate. //! \param arg is either a constant scale factor or an Envelope //! describing the time-varying scale factor. // template< class Iter, class Arg > void setBandwidth( Iter b, Iter e, const Arg & arg ) { BandwidthSetter setter( arg ); while ( b != e ) { setter( *b++ ); } } // --------------------------------------------------------------------------- // FrequencyScaler // //! Scale the frequency of the specified Partial according to //! an envelope representing a time-varying bandwidth scale value. // class FrequencyScaler : public PartialMutator { public: //! Construct a new FrequencyScaler from a constant scale factor. FrequencyScaler( double x ) : PartialMutator( x ) {} //! Construct a new FrequencyScaler from an Envelope representing //! a time-varying scale factor. FrequencyScaler( const Envelope & e ) : PartialMutator( e ) {} //! Function call operator: apply a scale factor to the specified //! Partial. void operator()( Partial & p ) const; }; // --------------------------------------------------------------------------- // scaleFrequency // --------------------------------------------------------------------------- //! Scale the frequency of the specified Partial according to //! an envelope representing a frequency scale value or envelope. //! //! \param p is a Partial to mutate. //! \param arg is either a constant scale factor or an Envelope //! describing the time-varying scale factor. // template< class Arg > void scaleFrequency( Partial & p, const Arg & arg ) { FrequencyScaler scaler( arg ); scaler( p ); } // --------------------------------------------------------------------------- // scaleFrequency // --------------------------------------------------------------------------- //! Scale the frequency of a sequence of Partials according to //! an envelope representing a frequency scale value or envelope. //! //! \param b is the beginning of a sequence of Partials to mutate. //! \param e is the end of a sequence of Partials to mutate. //! \param arg is either a constant scale factor or an Envelope //! describing the time-varying scale factor. // template< class Iter, class Arg > void scaleFrequency( Iter b, Iter e, const Arg & arg ) { FrequencyScaler scaler( arg ); while ( b != e ) { scaler( *b++ ); } } // --------------------------------------------------------------------------- // NoiseRatioScaler // //! Scale the relative noise content of the specified Partial according //! to an envelope representing a time-varying bandwidth scale value. // class NoiseRatioScaler : public PartialMutator { public: //! Construct a new NoiseRatioScaler from a constant scale factor. NoiseRatioScaler( double x ) : PartialMutator( x ) {} //! Construct a new NoiseRatioScaler from an Envelope representing //! a time-varying scale factor. NoiseRatioScaler( const Envelope & e ) : PartialMutator( e ) {} //! Function call operator: apply a scale factor to the specified //! Partial. void operator()( Partial & p ) const; }; // --------------------------------------------------------------------------- // scaleNoiseRatio // --------------------------------------------------------------------------- //! Scale the relative noise content of the specified Partial according to //! an envelope representing a scale value or envelope. //! //! \param p is a Partial to mutate. //! \param arg is either a constant scale factor or an Envelope //! describing the time-varying scale factor. // template< class Arg > void scaleNoiseRatio( Partial & p, const Arg & arg ) { NoiseRatioScaler scaler( arg ); scaler( p ); } // --------------------------------------------------------------------------- // scaleNoiseRatio // --------------------------------------------------------------------------- //! Scale the relative noise content of a sequence of Partials according to //! an envelope representing a scale value or envelope. //! //! \param b is the beginning of a sequence of Partials to mutate. //! \param e is the end of a sequence of Partials to mutate. //! \param arg is either a constant scale factor or an Envelope //! describing the time-varying scale factor. // template< class Iter, class Arg > void scaleNoiseRatio( Iter b, Iter e, const Arg & arg ) { NoiseRatioScaler scaler( arg ); while ( b != e ) { scaler( *b++ ); } } // --------------------------------------------------------------------------- // PitchShifter // //! Shift the pitch of the specified Partial according to //! the given pitch envelope. The pitch envelope is assumed to have //! units of cents (1/100 of a halfstep). // class PitchShifter : public PartialMutator { public: //! Construct a new PitchShifter from a constant scale factor. PitchShifter( double x ) : PartialMutator( x ) {} //! Construct a new PitchShifter from an Envelope representing //! a time-varying scale factor. PitchShifter( const Envelope & e ) : PartialMutator( e ) {} //! Function call operator: apply a scale factor to the specified //! Partial. void operator()( Partial & p ) const; }; // --------------------------------------------------------------------------- // shiftPitch // --------------------------------------------------------------------------- //! Shift the pitch of the specified Partial according to //! an envelope representing a pitch value or envelope. //! //! \param p is a Partial to mutate. //! \param arg is either a constant pitch factor or an Envelope //! describing the time-varying pitch factor in cents (1/100 of a //! halfstep). // template< class Arg > void shiftPitch( Partial & p, const Arg & arg ) { PitchShifter shifter( arg ); shifter( p ); } // --------------------------------------------------------------------------- // shiftPitch // --------------------------------------------------------------------------- //! Shift the pitch of a sequence of Partials according to //! an envelope representing a pitch value or envelope. //! //! \param b is the beginning of a sequence of Partials to mutate. //! \param e is the end of a sequence of Partials to mutate. //! \param arg is either a constant pitch factor or an Envelope //! describing the time-varying pitch factor in cents (1/100 of a //! halfstep). // template< class Iter, class Arg > void shiftPitch( Iter b, Iter e, const Arg & arg ) { PitchShifter shifter( arg ); while ( b != e ) { shifter( *b++ ); } } // These ones are not derived from PartialMutator, because // they don't use an Envelope and cannot be time-varying. // --------------------------------------------------------------------------- // Cropper // //! Trim a Partial by removing Breakpoints outside a specified time span. //! Insert a Breakpoint at the boundary when cropping occurs. class Cropper { public: //! Construct a new Cropper from a pair of times (in seconds) //! representing the span of time to which Partials should be //! cropped. Cropper( double t1, double t2 ) : minTime( std::min( t1, t2 ) ), maxTime( std::max( t1, t2 ) ) { } //! Function call operator: crop the specified Partial. //! Trim a Partial by removing Breakpoints outside the span offset //! [minTime, maxTime]. Insert a Breakpoint at the boundary when //! cropping occurs. void operator()( Partial & p ) const; private: double minTime, maxTime; }; // --------------------------------------------------------------------------- // crop // --------------------------------------------------------------------------- //! Trim a Partial by removing Breakpoints outside a specified time span. //! Insert a Breakpoint at the boundary when cropping occurs. //! //! This operation may leave the Partial empty, if it previously had //! no Breakpoints in the span [t1,t2]. //! //! \param p is the Partial to crop. //! \param t1 is the beginning of the time span to which the Partial //! should be cropped. //! \param t2 is the end of the time span to which the Partial //! should be cropped. // inline void crop( Partial & p, double t1, double t2 ) { Cropper cropper( t1, t2 ); cropper( p ); } // --------------------------------------------------------------------------- // crop // --------------------------------------------------------------------------- //! Trim a sequence of Partials by removing Breakpoints outside a specified //! time span. Insert a Breakpoint at the boundary when cropping occurs. //! //! This operation may leave some empty Partials, if they previously had //! no Breakpoints in the span [t1,t2]. //! //! \param b is the beginning of a sequence of Partials to crop. //! \param e is the end of a sequence of Partials to crop. //! \param t1 is the beginning of the time span to which the Partials //! should be cropped. //! \param t2 is the end of the time span to which the Partials //! should be cropped. // template< class Iter > void crop( Iter b, Iter e, double t1, double t2 ) { Cropper cropper( t1, t2 ); while ( b != e ) { cropper( *b++ ); } } // --------------------------------------------------------------------------- // TimeShifter // //! Shift the time of all the Breakpoints in a Partial by a //! constant amount. // class TimeShifter { public: //! Construct a new TimeShifter from a constant offset in seconds. TimeShifter( double x ) : offset( x ) {} //! Function call operator: apply a time shift to the specified //! Partial. void operator()( Partial & p ) const; private: double offset; }; // --------------------------------------------------------------------------- // shiftTime // --------------------------------------------------------------------------- //! Shift the time of all the Breakpoints in a Partial by a //! constant amount. //! //! \param p is a Partial to shift. //! \param offset is a constant offset in seconds. // inline void shiftTime( Partial & p, double offset ) { TimeShifter shifter( offset ); shifter( p ); } // --------------------------------------------------------------------------- // shiftTime // --------------------------------------------------------------------------- //! Shift the time of all the Breakpoints in a Partial by a //! constant amount. //! //! \param b is the beginning of a sequence of Partials to shift. //! \param e is the end of a sequence of Partials to shift. //! \param offset is a constant offset in seconds. // template< class Iter > void shiftTime( Iter b, Iter e, double offset ) { TimeShifter shifter( offset ); while ( b != e ) { shifter( *b++ ); } } // --------------------------------------------------------------------------- // timeSpan // --------------------------------------------------------------------------- //! Return the time (in seconds) spanned by a specified half-open //! range of Partials as a std::pair composed of the earliest //! Partial start time and latest Partial end time in the range. // template < typename Iterator > std::pair< double, double > timeSpan( Iterator begin, Iterator end ) { double tmin = 0., tmax = 0.; if ( begin != end ) { Iterator it = begin; tmin = it->startTime(); tmax = it->endTime(); while( it != end ) { tmin = std::min( tmin, it->startTime() ); tmax = std::max( tmax, it->endTime() ); ++it; } } return std::make_pair( tmin, tmax ); } // --------------------------------------------------------------------------- // peakAmplitude // --------------------------------------------------------------------------- //! Return the maximum amplitude achieved by a Partial. //! //! \param p is the Partial to evaluate //! \return the maximum (absolute) amplitude achieved by //! the partial p // double peakAmplitude( const Partial & p ); // --------------------------------------------------------------------------- // avgAmplitude // --------------------------------------------------------------------------- //! Return the average amplitude over all Breakpoints in this Partial. //! Return zero if the Partial has no Breakpoints. //! //! \param p is the Partial to evaluate //! \return the average amplitude of Breakpoints in the Partial p // double avgAmplitude( const Partial & p ); // --------------------------------------------------------------------------- // avgFrequency // --------------------------------------------------------------------------- //! Return the average frequency over all Breakpoints in this Partial. //! Return zero if the Partial has no Breakpoints. //! //! \param p is the Partial to evaluate //! \return the average frequency (Hz) of Breakpoints in the Partial p // double avgFrequency( const Partial & p ); // --------------------------------------------------------------------------- // weightedAvgFrequency // --------------------------------------------------------------------------- //! Return the average frequency over all Breakpoints in this Partial, //! weighted by the Breakpoint amplitudes. //! Return zero if the Partial has no Breakpoints. //! //! \param p is the Partial to evaluate //! \return the average frequency (Hz) of Breakpoints in the Partial p // double weightedAvgFrequency( const Partial & p ); // -- phase maintenance functions -- // --------------------------------------------------------------------------- // fixPhaseBefore // --------------------------------------------------------------------------- //! Recompute phases of all Breakpoints earlier than the specified time //! so that the synthesized 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 ); // --------------------------------------------------------------------------- // fixPhaseBefore (range) // --------------------------------------------------------------------------- //! Recompute phases of all Breakpoints earlier than the specified time //! so that the synthesized 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 b The beginning of a range of Partials whose phases //! should be fixed. //! \param e The end of a range of Partials whose phases //! should be fixed. //! \param t The time before which phases should be adjusted. // template < class Iter > void fixPhaseBefore( Iter b, Iter e, double t ) { while ( b != e ) { fixPhaseBefore( *b, t ); ++b; } } // --------------------------------------------------------------------------- // fixPhaseAfter // --------------------------------------------------------------------------- //! Recompute phases of all Breakpoints later than the specified time //! so that the synthesized 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 ); // --------------------------------------------------------------------------- // fixPhaseAfter (range) // --------------------------------------------------------------------------- //! Recompute phases of all Breakpoints later than the specified time //! so that the synthesized 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 b The beginning of a range of Partials whose phases //! should be fixed. //! \param e The end of a range of Partials whose phases //! should be fixed. //! \param t The time after which phases should be adjusted. // template < class Iter > void fixPhaseAfter( Iter b, Iter e, double t ) { while ( b != e ) { fixPhaseAfter( *b, t ); ++b; } } // --------------------------------------------------------------------------- // 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. //! //! \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 ); // --------------------------------------------------------------------------- // fixPhaseForward (range) // --------------------------------------------------------------------------- //! 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 b The beginning of a range of Partials whose phases //! should be fixed. //! \param e The end of a range of Partials 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. // template < class Iter > void fixPhaseForward( Iter b, Iter e, double tbeg, double tend ) { while ( b != e ) { fixPhaseForward( *b, tbeg, tend ); ++b; } } // --------------------------------------------------------------------------- // fixPhaseAt // --------------------------------------------------------------------------- //! Recompute phases of all Breakpoints in a Partial //! so that the synthesized phases match the stored phases, //! and the synthesized phase at (nearest) 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. Forward phase fixing is only applied //! to non-null (nonzero-amplitude) Breakpoints. 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 at which phases should be made correct. // void fixPhaseAt( Partial & p, double t ); // --------------------------------------------------------------------------- // fixPhaseAt (range) // --------------------------------------------------------------------------- //! Recompute phases of all Breakpoints in a Partial //! so that the synthesize phases match the stored phases, //! and the synthesized phase at (nearest) 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. Forward phase fixing is only applied //! to non-null (nonzero-amplitude) Breakpoints. If a null is encountered, //! its phase is simply left unmodified, and future phases wil be //! recomputed from that one. //! //! \param b The beginning of a range of Partials whose phases //! should be fixed. //! \param e The end of a range of Partials whose phases //! should be fixed. //! \param t The time at which phases should be made correct. // template < class Iter > void fixPhaseAt( Iter b, Iter e, double t ) { while ( b != e ) { fixPhaseAt( *b, t ); ++b; } } // --------------------------------------------------------------------------- // 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 Thre must be at least one Breakpoint in the //! Partial between the specified times t1 and t2. //! If this condition is not met, the Partial is //! unmodified. //! \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 t1 The time before which Partial frequencies and phases will //! not be modified. //! \param t2 The time after which Partial frequencies and phases will //! not be modified. Should be greater than t1, or else they //! will be swapped. // void fixPhaseBetween( Partial & p, double t1, double t2 ); // --------------------------------------------------------------------------- // fixPhaseBetween (range) // --------------------------------------------------------------------------- //! 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 Thre must be at least one Breakpoint in each //! Partial between the specified times t1 and t2. //! If this condition is not met, the Partial is //! unmodified. //! \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 b The beginning of a range of Partials whose phases //! should be fixed. //! \param e The end of a range of Partials whose phases //! should be fixed. //! \param t1 The time before which Partial frequencies and phases will //! not be modified. //! \param t2 The time after which Partial frequencies and phases will //! not be modified. Should be greater than t1, or else they //! will be swapped. // template < class Iter > void fixPhaseBetween( Iter b, Iter e, double t1, double t2 ) { while ( b != e ) { fixPhaseBetween( *b, t1, t2 ); ++b; } } // -- predicates -- // --------------------------------------------------------------------------- // isDurationLess // //! Predicate functor returning true if the duration of its //! Partial argument is less than the specified duration in //! seconds, and false otherwise. // class isDurationLess : public std::unary_function< const Partial, bool > { public: //! Initialize a new instance with the specified label. isDurationLess( double x ) : mDurationSecs(x) {} //! Function call operator: evaluate a Partial. bool operator()( const Partial & p ) const { return p.duration() < mDurationSecs; } //! Function call operator: evaluate a Partial pointer. bool operator()( const Partial * p ) const { return p->duration() < mDurationSecs; } private: double mDurationSecs; }; // --------------------------------------------------------------------------- // isLabelEqual // //! Predicate functor returning true if the label of its Partial argument is //! equal to the specified 32-bit label, and false otherwise. // class isLabelEqual : public std::unary_function< const Partial, bool > { public: //! Initialize a new instance with the specified label. isLabelEqual( int l ) : label(l) {} //! Function call operator: evaluate a Partial. bool operator()( const Partial & p ) const { return p.label() == label; } //! Function call operator: evaluate a Partial pointer. bool operator()( const Partial * p ) const { return p->label() == label; } private: int label; }; // --------------------------------------------------------------------------- // isLabelGreater // //! Predicate functor returning true if the label of its Partial argument is //! greater than the specified 32-bit label, and false otherwise. // class isLabelGreater : public std::unary_function< const Partial, bool > { public: //! Initialize a new instance with the specified label. isLabelGreater( int l ) : label(l) {} //! Function call operator: evaluate a Partial. bool operator()( const Partial & p ) const { return p.label() > label; } //! Function call operator: evaluate a Partial pointer. bool operator()( const Partial * p ) const { return p->label() > label; } private: int label; }; // --------------------------------------------------------------------------- // isLabelLess // //! Predicate functor returning true if the label of its Partial argument is //! less than the specified 32-bit label, and false otherwise. // class isLabelLess : public std::unary_function< const Partial, bool > { public: //! Initialize a new instance with the specified label. isLabelLess( int l ) : label(l) {} //! Function call operator: evaluate a Partial. bool operator()( const Partial & p ) const { return p.label() < label; } //! Function call operator: evaluate a Partial pointer. bool operator()( const Partial * p ) const { return p->label() < label; } private: int label; }; // --------------------------------------------------------------------------- // isPeakLess // //! Predicate functor returning true if the peak amplitude achieved by its //! Partial argument is less than the specified absolute amplitude, and //! false otherwise. // class isPeakLess : public std::unary_function< const Partial, bool > { public: //! Initialize a new instance with the specified peak amplitude. isPeakLess( double x ) : thresh(x) {} //! Function call operator: evaluate a Partial. bool operator()( const Partial & p ) const { return peakAmplitude( p ) < thresh; } //! Function call operator: evaluate a Partial pointer. bool operator()( const Partial * p ) const { return peakAmplitude( *p ) < thresh; } private: double thresh; }; // -- comparitors -- // --------------------------------------------------------------------------- // compareLabelLess // //! Comparitor (binary) functor returning true if its first Partial //! argument has a label whose 32-bit integer representation is less than //! that of the second Partial argument's label, and false otherwise. // class compareLabelLess : public std::binary_function< const Partial, const Partial, bool > { public: //! Compare two Partials, return true if its first Partial //! argument has a label whose 32-bit integer representation is less than //! that of the second Partial argument's label, and false otherwise. bool operator()( const Partial & lhs, const Partial & rhs ) const { return lhs.label() < rhs.label(); } //! Compare two Partials, return true if its first Partial //! argument has a label whose 32-bit integer representation is less than //! that of the second Partial argument's label, and false otherwise. bool operator()( const Partial * lhs, const Partial * rhs ) const { return lhs->label() < rhs->label(); } }; // --------------------------------------------------------------------------- // compareDurationLess // //! Comparitor (binary) functor returning true if its first Partial //! argument has duration less than that of the second Partial //! argument, and false otherwise. // class compareDurationLess : public std::binary_function< const Partial, const Partial, bool > { public: //! Compare two Partials, return true if its first Partial //! argument has duration less than that of the second Partial //! argument, and false otherwise. bool operator()( const Partial & lhs, const Partial & rhs ) const { return lhs.duration() < rhs.duration(); } //! Compare two Partials, return true if its first Partial //! argument has duration less than that of the second Partial //! argument, and false otherwise. bool operator()( const Partial * lhs, const Partial * rhs ) const { return lhs->duration() < rhs->duration(); } }; // --------------------------------------------------------------------------- // compareDurationGreater // //! Comparitor (binary) functor returning true if its first Partial //! argument has duration greater than that of the second Partial //! argument, and false otherwise. // class compareDurationGreater : public std::binary_function< const Partial, const Partial, bool > { public: //! Compare two Partials, return true if its first Partial //! argument has duration greater than that of the second Partial //! argument, and false otherwise. bool operator()( const Partial & lhs, const Partial & rhs ) const { return lhs.duration() > rhs.duration(); } //! Compare two Partials, return true if its first Partial //! argument has duration greater than that of the second Partial //! argument, and false otherwise. bool operator()( const Partial * lhs, const Partial * rhs ) const { return lhs->duration() > rhs->duration(); } }; // --------------------------------------------------------------------------- // compareStartTimeLess // //! Comparitor (binary) functor returning true if its first Partial //! argument has start time earlier than that of the second Partial //! argument, and false otherwise. // class compareStartTimeLess : public std::binary_function< const Partial, const Partial, bool > { public: //! Compare two Partials, return true if its first Partial //! argument has start time earlier than that of the second Partial //! argument, and false otherwise. bool operator()( const Partial & lhs, const Partial & rhs ) const { return lhs.startTime() < rhs.startTime(); } //! Compare two Partials, return true if its first Partial //! argument has start time earlier than that of the second Partial //! argument, and false otherwise. bool operator()( const Partial * lhs, const Partial * rhs ) const { return lhs->startTime() < rhs->startTime(); } }; } // end of namespace PartialUtils } // end of namespace Loris #endif /* ndef INCLUDE_PARTIALUTILS_H */