summaryrefslogtreecommitdiff
path: root/src/loris/PartialUtils.h
diff options
context:
space:
mode:
authorJohn Glover <glover.john@gmail.com>2011-07-08 18:06:21 +0100
committerJohn Glover <glover.john@gmail.com>2011-07-08 18:06:21 +0100
commitd6073e01c933c77f1e2bc3c3fe1126d617003549 (patch)
tree695d23677c5b84bf3a0f88fbd4959b4f7cbc0e90 /src/loris/PartialUtils.h
parent641688b252da468eb374674a0dbaae1bbac70b2b (diff)
downloadsimpl-d6073e01c933c77f1e2bc3c3fe1126d617003549.tar.gz
simpl-d6073e01c933c77f1e2bc3c3fe1126d617003549.tar.bz2
simpl-d6073e01c933c77f1e2bc3c3fe1126d617003549.zip
Start adding Loris files
Diffstat (limited to 'src/loris/PartialUtils.h')
-rw-r--r--src/loris/PartialUtils.h1189
1 files changed, 1189 insertions, 0 deletions
diff --git a/src/loris/PartialUtils.h b/src/loris/PartialUtils.h
new file mode 100644
index 0000000..afc6895
--- /dev/null
+++ b/src/loris/PartialUtils.h
@@ -0,0 +1,1189 @@
+#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 <functional>
+#include <utility>
+
+// 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 */