#ifndef INCLUDE_PARTIAL_H #define INCLUDE_PARTIAL_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 * * * Partial.h * * Definition of class Loris::Partial, and definitions and implementations of * classes of const and non-const iterators over Partials, and the exception * class InvalidPartial, thrown by some Partial members when invoked on a * degenerate Partial having no Breakpoints. * * Kelly Fitz, 16 Aug 1999 * loris@cerlsoundgroup.org * * http://www.cerlsoundgroup.org/Loris/ * */ #include "Breakpoint.h" #include "LorisExceptions.h" #include //#include //#include // begin namespace namespace Loris { class Partial_Iterator; class Partial_ConstIterator; // --------------------------------------------------------------------------- // class Partial // //! An instance of class Partial represents a single component in the //! reassigned bandwidth-enhanced additive model. A Partial consists of a //! chain of Breakpoints describing the time-varying frequency, amplitude, //! and bandwidth (or noisiness) envelopes of the component, and a 4-byte //! label. The Breakpoints are non-uniformly distributed in time. For more //! information about Reassigned Bandwidth-Enhanced Analysis and the //! Reassigned Bandwidth-Enhanced Additive Sound Model, refer to the Loris //! website: www.cerlsoundgroup.org/Loris/. //! //! The constituent time-tagged Breakpoints are accessible through //! Partial:iterator and Partial::const_iterator interfaces. //! These iterator classes implement the interface for bidirectional //! iterators in the STL, including pre and post-increment and decrement, //! and dereferencing. Dereferencing a Partial::itertator or //! Partial::const_itertator yields a reference to a Breakpoint. Additionally, //! these iterator classes have breakpoint() and time() members, returning //! the Breakpoint (by reference) at the current iterator position and the //! time (by value) corresponding to that Breakpoint. //! //! Partial is a leaf class, do not subclass. //! //! Most of the implementation of Partial delegates to a few //! container-dependent members. The following members are //! container-dependent, the other members are implemented in //! terms of these: //! default construction //! copy (construction) //! operator= (assign) //! operator== (equivalence) //! size //! insert( pos, Breakpoint ) //! erase( b, e ) //! findAfter( time ) //! begin (const and non-const) //! end (const and non-const) //! first (const and non-const) //! last (const and non-const) // class Partial { // -- public interface -- public: // -- types -- //! underlying Breakpoint container type, used by //! the iterator types defined below: typedef std::map< double, Breakpoint > container_type; // typedef std::vector< std::pair< double, Breakpoint > > container_type; // see Partial.C for a discussion of issues surrounding the // choice of std::map as a Breakpoint container. //! 32 bit type for labeling Partials typedef int label_type; //! non-const iterator over (time, Breakpoint) pairs in this Partial typedef Partial_Iterator iterator; //! const iterator over (time, Breakpoint) pairs in this Partial typedef Partial_ConstIterator const_iterator; //! size type for number of Breakpoints in this Partial typedef container_type::size_type size_type; // -- construction -- //! Retun a new empty (no Breakpoints) Partial. Partial( void ); //! Retun a new Partial from a half-open (const) iterator range //! of time-Breakpoint pairs. //! //! \param beg is the beginning of the range of time-Breakpoint //! pairs to insert into the new Partial. //! \param end is the end of the range of time-Breakpoint pairs //! to insert into the new Partial. Partial( const_iterator beg, const_iterator end ); //! Return a new Partial that is an exact copy (has an identical set //! of Breakpoints, at identical times, and the same label) of another //! Partial. //! //! \param other is the Partial to copy. Partial( const Partial & other ); //! Destroy this Partial. ~Partial( void ); // -- assignment -- //! Make this Partial an exact copy (has an identical set of //! Breakpoints, at identical times, and the same label) of another //! Partial. //! //! \param other is the Partial to copy. Partial & operator=( const Partial & other ); // -- container-dependent implementation -- //! Return an iterator refering to the position of the first //! Breakpoint in this Partial's envelope, or end() if there //! are no Breakpoints in the Partial. iterator begin( void ); //! Return a const iterator refering to the position of the first //! Breakpoint in this Partial's envelope, or end() if there //! are no Breakpoints in the Partial. const_iterator begin( void ) const; //! Return an iterator refering to the position past the last //! Breakpoint in this Partial's envelope. The iterator returned by //! end() (like the iterator returned by the end() member of any STL //! container) does not refer to a valid Breakpoint. iterator end( void ); //! Return a const iterator refering to the position past the last //! Breakpoint in this Partial's envelope. The iterator returned by //! end() (like the iterator returned by the end() member of any STL //! container) does not refer to a valid Breakpoint. const_iterator end( void ) const; //! Breakpoint removal: erase the Breakpoints in the specified range, //! and return an iterator referring to the position after the, //! erased range. //! //! \param beg is the beginning of the range of Breakpoints to erase //! \param end is the end of the range of Breakpoints to erase //! \return The position of the first Breakpoint after the range //! of removed Breakpoints, or end() if the last Breakpoint //! in the Partial was removed. iterator erase( iterator beg, iterator end ); //! Return an iterator refering to the insertion position for a //! Breakpoint at the specified time (that is, the position of the first //! Breakpoint at a time later than the specified time). //! //! \param time is the time in seconds to find //! \return The last position (iterator) at which a Breakpoint at the //! specified time could be inserted (the position of the //! first Breakpoint later than time). iterator findAfter( double time ); //! Return a const iterator refering to the insertion position for a //! Breakpoint at the specified time (that is, the position of the first //! Breakpoint at a time later than the specified time). //! //! \param time is the time in seconds to find //! \return The last position (iterator) at which a Breakpoint at the //! specified time could be inserted (the position of the //! first Breakpoint later than time). const_iterator findAfter( double time ) const; //! Breakpoint insertion: insert a copy of the specified Breakpoint in the //! parameter envelope at time (seconds), and return an iterator //! refering to the position of the inserted Breakpoint. //! //! \param time is the time in seconds at which to insert the new //! Breakpoint. //! \param bp is the new Breakpoint to insert. //! \return the position (iterator) of the newly-inserted //! time-Breakpoint pair. iterator insert( double time, const Breakpoint & bp ); //! Return the number of Breakpoints in this Partial. //! //! \return The number of Breakpoints in this Partial. size_type size( void ) const; // -- access -- //! Return the duration (in seconds) spanned by the Breakpoints in //! this Partial. Note that the synthesized onset time will differ, //! depending on the fade time used to synthesize this Partial (see //! class Synthesizer). double duration( void ) const; //! Return the time (in seconds) of the last Breakpoint in this //! Partial. Note that the synthesized onset time will differ, //! depending on the fade time used to synthesize this Partial (see //! class Synthesizer). double endTime( void ) const; //! Return a reference to the first Breakpoint in the Partial's //! envelope. //! //! \throw InvalidPartial if there are no Breakpoints. Breakpoint & first( void ); //! Return a const reference to the first Breakpoint in the Partial's //! envelope. //! //! \throw InvalidPartial if there are no Breakpoints. const Breakpoint & first( void ) const; //! Return the phase (in radians) of this Partial at its start time //! (the phase of the first Breakpoint). Note that the initial //! synthesized phase will differ, depending on the fade time used //! to synthesize this Partial (see class Synthesizer). double initialPhase( void ) const; //! Return the 32-bit label for this Partial as an integer. label_type label( void ) const; //! Return a reference to the last Breakpoint in the Partial's //! envelope. //! //! \throw InvalidPartial if there are no Breakpoints. Breakpoint & last( void ); //! Return a const reference to the last Breakpoint in the Partial's //! envelope. //! //! \throw InvalidPartial if there are no Breakpoints. const Breakpoint & last( void ) const; //! Same as size(). Return the number of Breakpoints in this Partial. size_type numBreakpoints( void ) const; //! Return the time (in seconds) of the first Breakpoint in this //! Partial. Note that the synthesized onset time will differ, //! depending on the fade time used to synthesize this Partial (see //! class Synthesizer). double startTime( void ) const; // -- mutation -- //! Absorb another Partial's energy as noise (bandwidth), //! by accumulating the other's energy as noise energy //! in the portion of this Partial's envelope that overlaps //! (in time) with the other Partial's envelope. //! //! \param other is the Partial to absorb. void absorb( const Partial & other ); //! Set the label for this Partial to the specified 32-bit value. void setLabel( label_type l ); //! Remove the Breakpoint at the position of the given //! iterator, invalidating the iterator. Return a //! iterator referring to the next valid position, or to //! the end of the Partial if the last Breakpoint is removed. //! //! \param pos is the position of the time-Breakpoint pair //! to be removed. //! \return The position (iterator) of the time-Breakpoint //! pair after the one that was removed. //! \post The iterator pos is invalid. iterator erase( iterator pos ); //! Return an iterator refering to the position of the //! Breakpoint in this Partial nearest the specified time. //! //! \param time is the time to find. //! \return The position (iterator) of the time-Breakpoint //! pair nearest (in time) to the specified time. iterator findNearest( double time ); //! Return a const iterator refering to the position of the //! Breakpoint in this Partial nearest the specified time. //! //! \param time is the time to find. //! \return The position (iterator) of the time-Breakpoint //! pair nearest (in time) to the specified time. const_iterator findNearest( double time ) const; //! Break this Partial at the specified position (iterator). //! The Breakpoint at the specified position becomes the first //! Breakpoint in a new Partial. Breakpoints at the specified //! position and subsequent positions are removed from this //! Partial and added to the new Partial, which is returned. //! //! \param pos is the position at which to split this Partial. //! \return A new Partial consisting of time-Breakpoint pairs //! beginning with pos and extending to the end of this //! Partial. //! \post All positions beginning with pos and extending to //! the end of this Partial have been removed. Partial split( iterator pos ); // -- parameter interpolation/extrapolation -- //! Define the default fade time for computing amplitude at the ends //! of a Partial. Floating point round-off errors make fadeTime == 0.0 //! dangerous and unpredictable. 1 ns is short enough to prevent rounding //! errors in the least significant bit of a 48-bit mantissa for times //! up to ten hours. //! //! 1 nanosecond, see Partial.C static const double ShortestSafeFadeTime; //! Return the interpolated amplitude of this Partial at the //! specified time. If non-zero fadeTime is specified, //! then the amplitude at the ends of the Partial is computed using //! a linear fade. The default fadeTime is ShortestSafeFadeTime, //! see the definition of ShortestSafeFadeTime, above. //! //! \param time is the time in seconds at which to evaluate the //! Partial. //! \param fadeTime is the duration in seconds over which Partial //! amplitudes fade at the ends. The default value is //! ShortestSafeFadeTime, 1 ns. //! \return The amplitude of this Partial at the specified time. //! \pre The Partial must have at least one Breakpoint. //! \throw InvalidPartial if the Partial has no Breakpoints. double amplitudeAt( double time, double fadeTime = ShortestSafeFadeTime ) const; //! Return the interpolated bandwidth (noisiness) coefficient of //! this Partial at the specified time. At times beyond the ends of //! the Partial, return the bandwidth coefficient at the nearest //! envelope endpoint. //! //! \param time is the time in seconds at which to evaluate the //! Partial. //! \return The bandwidth of this Partial at the specified time. //! \pre The Partial must have at least one Breakpoint. //! \throw InvalidPartial if the Partial has no Breakpoints. double bandwidthAt( double time ) const; //! Return the interpolated frequency (in Hz) of this Partial at the //! specified time. At times beyond the ends of the Partial, return //! the frequency at the nearest envelope endpoint. //! //! \param time is the time in seconds at which to evaluate the //! Partial. //! \return The frequency of this Partial at the specified time. //! \pre The Partial must have at least one Breakpoint. //! \throw InvalidPartial if the Partial has no Breakpoints. double frequencyAt( double time ) const; //! Return the interpolated phase (in radians) of this Partial at //! the specified time. At times beyond the ends of the Partial, //! return the extrapolated from the nearest envelope endpoint //! (assuming constant frequency, as reported by frequencyAt()). //! //! \param time is the time in seconds at which to evaluate the //! Partial. //! \return The phase of this Partial at the specified time. //! \pre The Partial must have at least one Breakpoint. //! \throw InvalidPartial if the Partial has no Breakpoints. double phaseAt( double time ) const; //! Return the interpolated parameters of this Partial at //! the specified time, same as building a Breakpoint from //! the results of frequencyAt, ampitudeAt, bandwidthAt, and //! phaseAt, but performs only one Breakpoint envelope search. //! If non-zero fadeTime is specified, then the //! amplitude at the ends of the Partial is coomputed using a //! linear fade. The default fadeTime is ShortestSafeFadeTime. //! //! \param time is the time in seconds at which to evaluate the //! Partial. //! \param fadeTime is the duration in seconds over which Partial //! amplitudes fade at the ends. The default value is //! ShortestSafeFadeTime, 1 ns. //! \return A Breakpoint describing the parameters of this Partial //! at the specified time. //! \pre The Partial must have at least one Breakpoint. //! \throw InvalidPartial if the Partial has no Breakpoints. Breakpoint parametersAt( double time, double fadeTime = ShortestSafeFadeTime ) const; // -- implementation -- private: label_type _label; container_type _breakpoints; // Breakpoint envelope }; // end of class Partial // --------------------------------------------------------------------------- // class Partial_Iterator // //! Non-const iterator for the Loris::Partial Breakpoint map. Wraps //! the non-const iterator for the (time,Breakpoint) pair container //! Partial::container_type. Partial_Iterator implements a //! bidirectional iterator interface, and additionally offers time //! and Breakpoint (reference) access through time() and breakpoint() //! members. // class Partial_Iterator { // -- instance variables -- typedef Partial::container_type BaseContainer; typedef BaseContainer::iterator BaseIterator; BaseIterator _iter; // -- public interface -- public: // -- bidirectional iterator interface -- //! The iterator category, for copmpatibility with //! C++ standard library algorithms typedef BaseIterator::iterator_category iterator_category; //! The type of element that can be accessed through this //! iterator (Breakpoint). typedef Breakpoint value_type; //! The type representing the distance between two of these //! iterators. typedef BaseIterator::difference_type difference_type; //! The type of a pointer to the type of element that can //! be accessed through this iterator (Breakpoint *). typedef Breakpoint * pointer; //! The type of a reference to the type of element that can //! be accessed through this iterator (Breakpoint &). typedef Breakpoint & reference; // construction: //! Construct a new iterator referring to no position in //! any Partial. Partial_Iterator( void ) {} // (allow compiler to generate copy, assignment, and destruction) // pre-increment/decrement: //! Pre-increment operator - advance the position of the iterator //! and return the iterator itself. //! //! \return This iterator (reference to self). //! \pre The iterator must be a valid position before the end //! in some Partial. Partial_Iterator& operator ++ () { ++_iter; return *this; } //! Pre-decrement operator - move the position of the iterator //! back by one and return the iterator itself. //! //! \return This iterator (reference to self). //! \pre The iterator must be a valid position after the beginning //! in some Partial. Partial_Iterator& operator -- () { --_iter; return *this; } // post-increment/decrement: //! Post-increment operator - advance the position of the iterator //! and return a copy of the iterator before it was advanced. //! The int argument is unused compiler magic. //! //! \return An iterator that is a copy of this iterator before //! being advanced. //! \pre The iterator must be a valid position before the end //! in some Partial. Partial_Iterator operator ++ ( int ) { return Partial_Iterator( _iter++ ); } //! Post-decrement operator - move the position of the iterator //! back by one and return a copy of the iterator before it was //! decremented. The int argument is unused compiler magic. //! //! \return An iterator that is a copy of this iterator before //! being decremented. //! \pre The iterator must be a valid position after the beginning //! in some Partial. Partial_Iterator operator -- ( int ) { return Partial_Iterator( _iter-- ); } // dereference (for treating Partial like a // STL collection of Breakpoints): //! Dereference operator. //! //! \return A reference to the Breakpoint at the position of this //! iterator. Breakpoint & operator * ( void ) const { return breakpoint(); } //! Dereference operator. //! //! \return A reference to the Breakpoint at the position of this //! iterator. //Breakpoint & operator * ( void ) { return breakpoint(); } //! Pointer operator. //! //! \return A pointer to the Breakpoint at the position of this //! iterator. Breakpoint * operator -> ( void ) const { return & breakpoint(); } //! Pointer operator. //! //! \return A pointer to the Breakpoint at the position of this //! iterator. //Breakpoint * operator -> ( void ) { return & breakpoint(); } // comparison: //! Equality comparison operator. //! //! \param lhs the iterator on the left side of the operator. //! \param rhs the iterator on the right side of the operator. //! \return true if the two iterators refer to the same position //! in the same Partial, false otherwise. friend bool operator == ( const Partial_Iterator & lhs, const Partial_Iterator & rhs ) { return lhs._iter == rhs._iter; } //! Inequality comparison operator. //! //! \param lhs the iterator on the left side of the operator. //! \param rhs the iterator on the right side of the operator. //! \return false if the two iterators refer to the same position //! in the same Partial, true otherwise. friend bool operator != ( const Partial_Iterator & lhs, const Partial_Iterator & rhs ) { return lhs._iter != rhs._iter; } // -- time and Breakpoint access -- //! Breakpoint accessor. //! //! \return A const reference to the Breakpoint at the position of this //! iterator. Breakpoint & breakpoint( void ) const { return _iter->second; } //! Breakpoint accessor. //! //! \return A reference to the Breakpoint at the position of this //! iterator. //Breakpoint & breakpoint( void ) // { return _iter->second; } //! Time accessor. //! //! \return The time in seconds of the Breakpoint at the position //! of this iterator. double time( void ) const { return _iter->first; } // -- BaseIterator conversions -- private: // construction by GenericBreakpointContainer from a BaseIterator: Partial_Iterator( const BaseIterator & it ) : _iter(it) {} friend class Partial; // befriend Partial_ConstIterator, // for const construction from non-const: friend class Partial_ConstIterator; }; // end of class Partial_Iterator // --------------------------------------------------------------------------- // class Partial_ConstIterator // //! Const iterator for the Loris::Partial Breakpoint map. Wraps //! the non-const iterator for the (time,Breakpoint) pair container //! Partial::container_type. Partial_Iterator implements a //! bidirectional iterator interface, and additionally offers time //! and Breakpoint (reference) access through time() and breakpoint() //! members. // class Partial_ConstIterator { // -- instance variables -- typedef Partial::container_type BaseContainer; typedef BaseContainer::const_iterator BaseIterator; BaseIterator _iter; // -- public interface -- public: // -- bidirectional iterator interface -- //! The iterator category, for copmpatibility with //! C++ standard library algorithms typedef BaseIterator::iterator_category iterator_category; //! The type of element that can be accessed through this //! iterator (Breakpoint). typedef Breakpoint value_type; //! The type representing the distance between two of these //! iterators. typedef BaseIterator::difference_type difference_type; //! The type of a pointer to the type of element that can //! be accessed through this iterator (const Breakpoint *). typedef const Breakpoint * pointer; //! The type of a reference to the type of element that can //! be accessed through this iterator (const Breakpoint &). typedef const Breakpoint & reference; // construction: //! Construct a new iterator referring to no position in //! any Partial. Partial_ConstIterator( void ) {} //! Construct a new const iterator from a non-const iterator. //! //! \param other a non-const iterator from which to make //! a read-only copy. Partial_ConstIterator( const Partial_Iterator & other ) : _iter( other._iter ) {} // (allow compiler to generate copy, assignment, and destruction): // pre-increment/decrement: //! Pre-increment operator - advance the position of the iterator //! and return the iterator itself. //! //! \return This iterator (reference to self). //! \pre The iterator must be a valid position before the end //! in some Partial. Partial_ConstIterator& operator ++ () { ++_iter; return *this; } //! Pre-decrement operator - move the position of the iterator //! back by one and return the iterator itself. //! //! \return This iterator (reference to self). //! \pre The iterator must be a valid position after the beginning //! in some Partial. Partial_ConstIterator& operator -- () { --_iter; return *this; } // post-increment/decrement: //! Post-increment operator - advance the position of the iterator //! and return a copy of the iterator before it was advanced. //! The int argument is unused compiler magic. //! //! \return An iterator that is a copy of this iterator before //! being advanced. //! \pre The iterator must be a valid position before the end //! in some Partial. Partial_ConstIterator operator ++ ( int ) { return Partial_ConstIterator( _iter++ ); } //! Post-decrement operator - move the position of the iterator //! back by one and return a copy of the iterator before it was //! decremented. The int argument is unused compiler magic. //! //! \return An iterator that is a copy of this iterator before //! being decremented. //! \pre The iterator must be a valid position after the beginning //! in some Partial. Partial_ConstIterator operator -- ( int ) { return Partial_ConstIterator( _iter-- ); } // dereference (for treating Partial like a // STL collection of Breakpoints): //! Dereference operator. //! //! \return A const reference to the Breakpoint at the position of this //! iterator. const Breakpoint & operator * ( void ) const { return breakpoint(); } //! Pointer operator. //! //! \return A const pointer to the Breakpoint at the position of this //! iterator. const Breakpoint * operator -> ( void ) const { return & breakpoint(); } // comparison: //! Equality comparison operator. //! //! \param lhs the iterator on the left side of the operator. //! \param rhs the iterator on the right side of the operator. //! \return true if the two iterators refer to the same position //! in the same Partial, false otherwise. friend bool operator == ( const Partial_ConstIterator & lhs, const Partial_ConstIterator & rhs ) { return lhs._iter == rhs._iter; } //! Inequality comparison operator. //! //! \param lhs the iterator on the left side of the operator. //! \param rhs the iterator on the right side of the operator. //! \return false if the two iterators refer to the same position //! in the same Partial, true otherwise. friend bool operator != ( const Partial_ConstIterator & lhs, const Partial_ConstIterator & rhs ) { return lhs._iter != rhs._iter; } // -- time and Breakpoint access -- //! Breakpoint accessor. //! //! \return A const reference to the Breakpoint at the position of this //! iterator. const Breakpoint & breakpoint( void ) const { return _iter->second; } //! Time accessor. //! //! \return The time in seconds of the Breakpoint at the position //! of this iterator. double time( void ) const { return _iter->first; } // -- BaseIterator conversions -- private: // construction by GenericBreakpointContainer from a BaseIterator: Partial_ConstIterator( BaseIterator it ) : _iter(it) {} friend class Partial; }; // end of class Partial_ConstIterator // --------------------------------------------------------------------------- // class InvalidPartial // //! Class of exceptions thrown when a Partial is found to be badly configured //! or otherwise invalid. // class InvalidPartial : public InvalidObject { public: //! Construct a new instance with the specified description and, optionally //! a string identifying the location at which the exception as thrown. The //! Throw( Exception_Class, description_string ) macro generates a location //! string automatically using __FILE__ and __LINE__. //! //! \param str is a string describing the exceptional condition //! \param where is an option string describing the location in //! the source code from which the exception was thrown //! (generated automatically byt he Throw macro). InvalidPartial( const std::string & str, const std::string & where = "" ) : InvalidObject( std::string("Invalid Partial -- ").append( str ), where ) {} }; // end of class InvalidPartial } // end of namespace Loris #endif /* ndef INCLUDE_PARTIAL_H */