#ifndef INCLUDE_DILATOR_H #define INCLUDE_DILATOR_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 * * * Dilator.h * * Definition of class Dilator. * * Kelly Fitz, 26 Oct 1999 * loris@cerlsoundgroup.org * * http://www.cerlsoundgroup.org/Loris/ * */ #if defined(NO_TEMPLATE_MEMBERS) #include "PartialList.h" #endif #include // begin namespace namespace Loris { class Marker; class Partial; // --------------------------------------------------------------------------- // class Dilator // //! Class Dilator represents an algorithm for non-uniformly expanding //! and contracting the Partial parameter envelopes according to the initial //! and target (desired) times of temporal features. //! //! It is frequently necessary to redistribute temporal events in this way //! in preparation for a sound morph. For example, when morphing instrument //! tones, it is common to align the attack, sustain, and release portions //! of the source sounds by dilating or contracting those temporal regions. //! //! This same procedure can be applied to the Markers stored in AiffFile, //! SdifFile, and SpcFile (see Marker.h). // class Dilator { // -- instance variables -- std::vector< double > _initial, _target; // time points // -- public interface -- public: // -- construction -- //! Construct a new Dilator with no time points. Dilator( void ); //! Construct a new Dilator using a range of initial time points //! and a range of target (desired) time points. The client must //! ensure that the target range has at least as many elements as //! the initial range. //! //! \param ibegin is the beginning of a sequence of initial, or source, //! time points. //! \param iend is (one-past) the end of a sequence of initial, or //! source, time points. //! \param tbegin is the beginning of a sequence of target time points; //! this sequence must be as long as the sequence of initial time //! point described by ibegin and iend. //! //! If compiled with NO_TEMPLATE_MEMBERS defined, this member accepts //! only const double * arguments. #if ! defined(NO_TEMPLATE_MEMBERS) template Dilator( Iter1 ibegin, Iter1 iend, Iter2 tbegin ); #else inline Dilator( const double * ibegin, const double * iend, const double * tbegin ); #endif // Use compiler-generated copy, assign, and destroy. // -- mutation -- //! Insert a pair of initial and target time points. //! //! Specify a pair of initial and target time points to be used //! by this Dilator, corresponding, for example, to the initial //! and desired time of a particular temporal feature in an //! analyzed sound. //! //! \param i is an initial, or source, time point //! \param t is a target time point //! //! The time points will be sorted before they are used. //! If, in the sequences of initial and target time points, there are //! exactly the same number of initial time points preceding i as //! target time points preceding t, then time i will be warped to //! time t in the dilation process. void insert( double i, double t ); // -- dilation -- //! Replace the Partial envelope with a new envelope having the //! same Breakpoints at times computed to align temporal features //! in the sorted sequence of initial time points with their //! counterparts the sorted sequence of target time points. //! //! Depending on the specification of initial and target time //! points, the dilated Partial may have Breakpoints at times //! less than 0, even if the original Partial did not. //! //! It is possible to have duplicate time points in either sequence. //! Duplicate initial time points result in very localized stretching. //! Duplicate target time points result in very localized compression. //! //! If all initial time points are greater than 0, then an implicit //! time point at 0 is assumed in both initial and target sequences, //! so the onset of a sound can be stretched without explcitly specifying a //! zero point in each vector. (This seems most intuitive, and only looks //! like an inconsistency if clients are using negative time points in //! their Dilator, or Partials having Breakpoints before time 0, both //! of which are probably unusual circumstances.) //! //! \param p is the Partial to dilate. void dilate( Partial & p ) const; //! Function call operator: same as dilate( Partial & p ). void operator() ( Partial & p ) const; //! Compute a new time for the specified Marker using //! warpTime(), exactly as Partial Breakpoint times are //! recomputed. This can be used to dilate the Markers //! corresponding to a collection of Partials. //! //! \param m is the Marker whose time should be recomputed. void dilate( Marker & m ) const; //! Function call operator: same as dilate( Marker & p ). void operator() ( Marker & m ) const; //! Non-uniformly expand and contract the parameter envelopes of the each //! Partial in the specified half-open range according to this Dilator's //! stored initial and target (desired) times. //! //! \param dilate_begin is the beginning of a sequence of Partials to dilate. //! \param dilate_end is (one-past) the end of a sequence of Partials to dilate. //! //! If compiled with NO_TEMPLATE_MEMBERS defined, this member accepts //! only PartialList::const_iterator arguments. Otherwise, this member //! also works for sequences of Markers. //! //! \sa Dilator::dilate( Partial & p ) const //! \sa Dilator::dilate( Marker & m ) const #if ! defined(NO_TEMPLATE_MEMBERS) template void dilate( Iter dilate_begin, Iter dilate_end ) const; #else inline void dilate( PartialList::iterator dilate_begin, PartialList::iterator dilate_end ) const; #endif //! Function call operator: same as //! dilate( Iter dilate_begin, Iter dilate_end ) //! //! If compiled with NO_TEMPLATE_MEMBERS defined, this member accepts //! only PartialList::const_iterator arguments. Otherwise, this member //! also works for sequences of Markers. //! //! \sa Dilator::dilate( Partial & p ) const //! \sa Dilator::dilate( Marker & m ) const #if ! defined(NO_TEMPLATE_MEMBERS) template void operator() ( Iter dilate_begin, Iter dilate_end ) const; #else inline void operator() ( PartialList::iterator dilate_begin, PartialList::iterator dilate_end ) const; #endif //! Return the dilated time value corresponding to the specified initial time. //! //! \param currentTime is a pre-dilated time. //! \return the dilated time corresponding to the initial time currentTime double warpTime( double currentTime ) const; // -- static members -- //! Static member that constructs an instance and applies //! it to a sequence of Partials. //! Construct a Dilator using the specified initial and //! target times, and apply it to a sequence of Partials. //! //! \param dilate_begin is the beginning of a sequence of Partials to dilate. //! \param dilate_end is (one-past) the end of a sequence of Partials to dilate. //! \param ibegin is the beginning of a sequence of initial, or source, //! time points. //! \param iend is (one-past) the end of a sequence of initial, or //! source, time points. //! \param tbegin is the beginning of a sequence of target time points; //! this sequence must be as long as the sequence of initial time //! point described by ibegin and iend. //! //! If compiled with NO_TEMPLATE_MEMBERS defined, this member accepts //! only PartialList::const_iterator arguments. Otherwise, this member //! also works for sequences of Markers. //! If compiled with NO_TEMPLATE_MEMBERS defined, this member accepts //! only const double * arguments for the times, otherwise, any iterator //! will do.. //! //! \sa Dilator::dilate( Partial & p ) const //! \sa Dilator::dilate( Marker & m ) const #if ! defined(NO_TEMPLATE_MEMBERS) template< typename PartialsIter, typename TimeIter1, typename TimeIter2 > static void dilate( PartialsIter dilate_begin, PartialsIter dilate_end, TimeIter1 ibegin, TimeIter1 iend, TimeIter2 tbegin ); #else static inline void dilate( PartialList::iterator dilate_begin, PartialList::iterator dilate_end, const double * ibegin, const double * iend, const double * tbegin ); #endif }; // end of class Dilator // --------------------------------------------------------------------------- // constructor (sequences of time points) // --------------------------------------------------------------------------- //! Construct a new Dilator using a range of initial time points //! and a range of target (desired) time points. The client must //! ensure that the target range has at least as many elements as //! the initial range. //! //! \param ibegin is the beginning of a sequence of initial, or source, //! time points. //! \param iend is (one-past) the end of a sequence of initial, or //! source, time points. //! \param tbegin is the beginning of a sequence of target time points; //! this sequence must be as long as the sequence of initial time //! point described by ibegin and iend. //! //! If compiled with NO_TEMPLATE_MEMBERS defined, this member accepts //! only const double * arguments. // #if ! defined(NO_TEMPLATE_MEMBERS) template Dilator::Dilator( Iter1 ibegin, Iter1 iend, Iter2 tbegin ) #else inline Dilator::Dilator( const double * ibegin, const double * iend, const double * tbegin ) #endif { while ( ibegin != iend ) { insert( *ibegin++, *tbegin++ ); } } // --------------------------------------------------------------------------- // dilate (sequence of Partials or Markers) // --------------------------------------------------------------------------- //! Non-uniformly expand and contract the parameter envelopes of the each //! Partial in the specified half-open range according to this Dilator's //! stored initial and target (desired) times. //! //! \param dilate_begin is the beginning of a sequence of Partials to dilate. //! \param dilate_end is (one-past) the end of a sequence of Partials to dilate. //! //! If compiled with NO_TEMPLATE_MEMBERS defined, this member accepts //! only PartialList::const_iterator arguments. Otherwise, this member //! also works for sequences of Markers. //! //! \sa Dilator::dilate( Partial & p ) const //! \sa Dilator::dilate( Marker & m ) const // #if ! defined(NO_TEMPLATE_MEMBERS) template void Dilator::dilate( Iter dilate_begin, Iter dilate_end ) const #else inline void Dilator::dilate( PartialList::iterator dilate_begin, PartialList::iterator dilate_end ) const #endif { while ( dilate_begin != dilate_end ) { dilate( *(dilate_begin++) ); } } // --------------------------------------------------------------------------- // Function call operator (sequence of Partials or Markers) // --------------------------------------------------------------------------- //! Function call operator: same as //! dilate( Iter dilate_begin, Iter dilate_end ) //! //! If compiled with NO_TEMPLATE_MEMBERS defined, this member accepts //! only PartialList::const_iterator arguments. Otherwise, this member //! also works for sequences of Markers. //! //! \sa Dilator::dilate( Partial & p ) const //! \sa Dilator::dilate( Marker & m ) const // #if ! defined(NO_TEMPLATE_MEMBERS) template void Dilator::operator() ( Iter dilate_begin, Iter dilate_end ) const #else inline void Dilator::operator() ( PartialList::iterator dilate_begin, PartialList::iterator dilate_end ) const #endif { dilate( dilate_begin, dilate_end ); } // --------------------------------------------------------------------------- // Function call operator (single Partial) // --------------------------------------------------------------------------- //! Function call operator: same as dilate( Partial & p ). //! //! \sa Dilator::dilate( Partial & p ) const // inline void Dilator::operator() ( Partial & p ) const { dilate( p ); } // --------------------------------------------------------------------------- // Function call operator (single Marker) // --------------------------------------------------------------------------- //! Function call operator: same as dilate( Marker & m ). //! //! \sa Dilator::dilate( Marker & m ) const // inline void Dilator::operator() ( Marker & m ) const { dilate( m ); } // --------------------------------------------------------------------------- // dilate (static) // --------------------------------------------------------------------------- //! Static member that constructs an instance and applies //! it to a sequence of Partials. //! Construct a Dilator using the specified initial and //! target times, and apply it to a sequence of Partials. //! //! \param dilate_begin is the beginning of a sequence of Partials to dilate. //! \param dilate_end is (one-past) the end of a sequence of Partials to dilate. //! \param ibegin is the beginning of a sequence of initial, or source, //! time points. //! \param iend is (one-past) the end of a sequence of initial, or //! source, time points. //! \param tbegin is the beginning of a sequence of target time points; //! this sequence must be as long as the sequence of initial time //! point described by ibegin and iend. //! //! If compiled with NO_TEMPLATE_MEMBERS defined, this member accepts //! only PartialList::const_iterator arguments. Otherwise, this member //! also works for sequences of Markers. //! If compiled with NO_TEMPLATE_MEMBERS defined, this member accepts //! only const double * arguments for the times, otherwise, any iterator //! will do.. //! //! \sa Dilator::dilate( Partial & p ) const //! \sa Dilator::dilate( Marker & m ) const // #if ! defined(NO_TEMPLATE_MEMBERS) template< typename PartialsIter, typename TimeIter1, typename TimeIter2 > void Dilator::dilate( PartialsIter dilate_begin, PartialsIter dilate_end, TimeIter1 ibegin, TimeIter1 iend, TimeIter2 tbegin ) #else inline void Dilator::dilate( PartialList::iterator dilate_begin, PartialList::iterator dilate_end, const double * ibegin, const double * iend, const double * tbegin ) #endif { Dilator instance( ibegin, iend, tbegin ); instance.dilate( dilate_begin, dilate_end ); } } // end of namespace Loris #endif /* ndef INCLUDE_DILATOR_H */