diff options
author | John Glover <glover.john@gmail.com> | 2011-07-08 18:06:21 +0100 |
---|---|---|
committer | John Glover <glover.john@gmail.com> | 2011-07-08 18:06:21 +0100 |
commit | d6073e01c933c77f1e2bc3c3fe1126d617003549 (patch) | |
tree | 695d23677c5b84bf3a0f88fbd4959b4f7cbc0e90 /src/loris/Resampler.h | |
parent | 641688b252da468eb374674a0dbaae1bbac70b2b (diff) | |
download | simpl-d6073e01c933c77f1e2bc3c3fe1126d617003549.tar.gz simpl-d6073e01c933c77f1e2bc3c3fe1126d617003549.tar.bz2 simpl-d6073e01c933c77f1e2bc3c3fe1126d617003549.zip |
Start adding Loris files
Diffstat (limited to 'src/loris/Resampler.h')
-rw-r--r-- | src/loris/Resampler.h | 449 |
1 files changed, 449 insertions, 0 deletions
diff --git a/src/loris/Resampler.h b/src/loris/Resampler.h new file mode 100644 index 0000000..bc45eb3 --- /dev/null +++ b/src/loris/Resampler.h @@ -0,0 +1,449 @@ +#ifndef INCLUDE_RESAMPLER_H +#define INCLUDE_RESAMPLER_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 + * + * + * Resampler.h + * + * Definition of class Resampler, for converting reassigned Partial envelopes + * into more conventional additive synthesis envelopes, having data points + * at regular time intervals. The benefits of reassigned analysis are NOT + * lost in this process, since the elimination of unreliable data and the + * reduction of temporal smearing are reflected in the resampled data. + * + * Lippold, 7 Aug 2003 + * loris@cerlsoundgroup.org + * + * http://www.cerlsoundgroup.org/Loris/ + * + */ + +#include "PartialList.h" +#include "LinearEnvelope.h" + +// begin namespace +namespace Loris { + +class Partial; + +// --------------------------------------------------------------------------- +// class Resampler +// +//! Class Resampler represents an algorithm for resampling Partial envelopes +//! at regular time intervals. Resampling makes the envelope data more suitable +//! for exchange (as SDIF data, for example) with other applications that +//! cannot process raw (continuously-distributed) reassigned data. Resampling +//! will often greatly reduce the size of the data (by greatly reducing the +//! number of Breakpoints in the Partials) without adversely affecting the +//! quality of the reconstruction. +// +class Resampler +{ +// --- public interface --- +public: +// --- lifecycle --- + + //! Initialize a Resampler having the specified uniform sampling + //! interval. Enable phase-correct resampling, in which frequencies + //! of resampled Partials are modified (using fixFrequency) such + //! that the resampled phases are achieved in synthesis. Phase- + //! correct resampling can be disabled using setPhaseCorrect. + //! + //! Resampled Partials will be composed of Breakpoints at every + //! integer multiple of the resampling interval. + //! + //! \sa setPhaseCorrect + //! \sa fixFrequency + //! + //! \param sampleInterval is the resampling interval in seconds, + //! Breakpoint data is computed at integer multiples of + //! sampleInterval seconds. + //! + //! \throw InvalidArgument if sampleInterval is not positive. + explicit Resampler( double sampleInterval ); + + + // --- use compiler-generated copy/assign/destroy --- + +// --- parameters --- + + //! Specify phase-corrected resampling, or not. If phase + //! correct, Partial frequencies are altered slightly + //! to match, as nearly as possible, the Breakpoint + //! phases after resampling. Phases are updated so that + //! the Partial frequencies and phases are consistent after + //! resampling. + //! + //! \param correctPhase is a boolean flag specifying that + //! (if true) frequency/phase correction should be + //! applied after resampling. + void setPhaseCorrect( bool correctPhase ); + +// --- resampling --- + + //! Resample the specified Partial using the stored quanitization interval. + //! The Breakpoint times will comprise a contiguous sequence of all integer + //! multiples of the sampling interval, starting and ending with the nearest + //! multiples to the ends of the Partial. If phase correct resampling is + //! specified (the default)≤ frequencies and phases are corrected to be in + //! agreement and to match as nearly as possible the resampled phases. + //! + //! Resampling is performed in-place. + //! + //! \param p is the Partial to resample + void resample( Partial & p ) const; + + //! Function call operator: same as resample( p ). + void operator() ( Partial & p ) const + { + resample( p ); + } + + //! Resample the specified Partial using the stored quanitization interval. + //! The Breakpoint times will comprise a contiguous sequence of all integer + //! multiples of the sampling interval, starting and ending with the nearest + //! multiples to the ends of the Partial. If phase correct resampling is + //! specified (the default)≤ frequencies and phases are corrected to be in + //! agreement and to match as nearly as possible the resampled phases. + //! + //! The timing envelope represents a warping of the time axis that is + //! applied during resampling. The Breakpoint times in resampled Partials + //! will a comprise contiguous sequence of all integer multiples of the + //! sampling interval between the first and last breakpoints in the timing + //! envelope, and each Breakpoint will represent the parameters of the + //! original Partial at the time that is the value of the timing envelope + //! at that instant. + //! + //! Resampling is performed in-place. + //! + //! \param p is the Partial to resample + //! + //! \param timingEnv is the timing envelope, a map of Breakpoint + //! times in resampled Partials onto parameter sampling + //! instants in the original Partials. + //! + //! \throw InvalidArgument if timingEnv has any negative breakpoint + //! times or values. + void resample( Partial & p, const LinearEnvelope & timingEnv ) const; + + //! Quantize the Breakpoint times using the specified Partial using the + //! stored quanitization interval. Each Breakpoint in the Partial is + //! replaced by a Breakpoint constructed by resampling the Partial at + //! the nearest integer multiple of the of the resampling interval. + //! + //! Quantization is performed in-place. + //! + //! \param p is the Partial to resample + void quantize( Partial & p ) const; + + + //! Resample all Partials in the specified (half-open) range using this + //! Resampler's stored quanitization interval. The Breakpoint times in + //! resampled Partials will comprise a contiguous sequence of all integer + //! multiples of the sampling interval, starting and ending with the nearest + //! multiples to the ends of the Partial. If phase correct resampling is + //! specified (the default)≤ frequencies and phases are corrected to be in + //! agreement and to match as nearly as possible the resampled phases. + //! + //! Resampling is performed in-place. + //! + //! \param begin is the beginning of the range of Partials to resample + //! \param end is (one-past) the end of the range of Partials to resample + //! + //! If compiled with NO_TEMPLATE_MEMBERS defined, then begin and end + //! must be PartialList::iterators, otherwise they can be any type + //! of iterators over a sequence of Partials. +#if ! defined(NO_TEMPLATE_MEMBERS) + template<typename Iter> + void resample( Iter begin, Iter end ) const; +#else + inline + void resample( PartialList::iterator begin, PartialList::iterator end ) const; +#endif + + //! Function call operator: same as resample( begin, end ). +#if ! defined(NO_TEMPLATE_MEMBERS) + template<typename Iter> + void operator()( Iter begin, Iter end ) const +#else + void operator()( PartialList::iterator begin, PartialList::iterator end ) const +#endif + { + resample( begin, end ); + } + + //! Resample all Partials in the specified (half-open) range using this + //! Resampler's stored quanitization interval. The Breakpoint times in + //! resampled Partials will comprise a contiguous sequence of all integer + //! multiples of the sampling interval, starting and ending with the nearest + //! multiples to the ends of the Partial. If phase correct resampling is + //! specified (the default)≤ frequencies and phases are corrected to be in + //! agreement and to match as nearly as possible the resampled phases. + //! + //! The timing envelope represents a warping of the time axis that is + //! applied during resampling. The Breakpoint times in resampled Partials + //! will a comprise contiguous sequence of all integer multiples of the + //! sampling interval between the first and last breakpoints in the timing + //! envelope, and each Breakpoint will represent the parameters of the + //! original Partial at the time that is the value of the timing envelope + //! at that instant. + //! + //! Resampling is performed in-place. + //! + //! \param begin is the beginning of the range of Partials to resample + //! \param end is (one-past) the end of the range of Partials to resample + //! \param timingEnv is the timing envelope, a map of Breakpoint + //! times in resampled Partials onto parameter sampling + //! instants in the original Partials. + //! + //! If compiled with NO_TEMPLATE_MEMBERS defined, then begin and end + //! must be PartialList::iterators, otherwise they can be any type + //! of iterators over a sequence of Partials. +#if ! defined(NO_TEMPLATE_MEMBERS) + template<typename Iter> + void resample( Iter begin, Iter end, const LinearEnvelope & timingEnv ) const; +#else + inline + void resample( PartialList::iterator begin, PartialList::iterator end, + const LinearEnvelope & timingEnv) const; +#endif + + //! Quantize all Partials in the specified (half-open) range. + //! Each Breakpoint in the Partials is replaced by a Breakpoint + //! constructed by resampling the Partial at the nearest + //! integer multiple of the of the resampling interval. + //! + //! \param begin is the beginning of the range of Partials to quantize + //! \param end is (one-past) the end of the range of Partials to quantize + //! + //! If compiled with NO_TEMPLATE_MEMBERS defined, then begin and end + //! must be PartialList::iterators, otherwise they can be any type + //! of iterators over a sequence of Partials. +#if ! defined(NO_TEMPLATE_MEMBERS) + template<typename Iter> + void quantize( Iter begin, Iter end ) const; +#else + inline + void quantize( PartialList::iterator begin, PartialList::iterator end ) const; +#endif + +// -- static members -- + + //! Static member that constructs an instance and applies + //! it to a sequence of Partials. + //! Construct a Resampler using the specified resampling + //! interval, and use it to channelize a sequence of Partials. + //! + //! \param begin is the beginning of a sequence of Partials to + //! resample. + //! \param end is the end of a sequence of Partials to + //! resample. + //! \param sampleInterval is the resampling interval in seconds, + //! Breakpoint data is computed at integer multiples of + //! sampleInterval seconds. + //! \param denseResampling is a boolean flag indicating that dense + //! resamping (Breakpoint at every integer multiple of the + //! resampling interval) should be performed. If false (the + //! default), sparse resampling (Breakpoints only at multiples + //! of the resampling interval near Breakpoint times in the + //! original Partial) is performed. + //! \throw InvalidArgument if sampleInterval is not positive. + //! + //! If compiled with NO_TEMPLATE_MEMBERS defined, then begin and end + //! must be PartialList::iterators, otherwise they can be any type + //! of iterators over a sequence of Partials. +#if ! defined(NO_TEMPLATE_MEMBERS) + template< typename Iter > + static + void resample( Iter begin, Iter end, double sampleInterval, + bool denseResampling = false ); +#else + static inline + void resample( PartialList::iterator begin, PartialList::iterator end, + double sampleInterval, bool denseResampling = false ); +#endif + +// --- instance variables --- +private: + + //! the resampling interval in seconds + double interval_; + + //! boolean flag selecting phase-corrected resampling + //! (default is true) + bool phaseCorrect_; + +}; // end of class Resampler + +// --------------------------------------------------------------------------- +// resample (sequence of Partials) +// --------------------------------------------------------------------------- +//! Resample all Partials in the specified (half-open) range using this +//! Resampler's stored sampling interval, so that the Breakpoints in +//! the Partial envelopes will all lie on a common temporal grid. +//! The Breakpoint times in the resampled Partial will comprise a +//! contiguous sequence of integer multiples of the sampling interval, +//! beginning with the multiple nearest to the Partial's start time and +//! ending with the multiple nearest to the Partial's end time. Resampling +//! is performed in-place. +//! +//! \param begin is the beginning of the range of Partials to resample +//! \param end is (one-past) the end of the range of Partials to resample +//! +//! If compiled with NO_TEMPLATE_MEMBERS defined, then begin and end +//! must be PartialList::iterators, otherwise they can be any type +//! of iterators over a sequence of Partials. +// +#if ! defined(NO_TEMPLATE_MEMBERS) +template<typename Iter> +void Resampler::resample( Iter begin, Iter end ) const +#else +inline +void Resampler::resample( PartialList::iterator begin, PartialList::iterator end ) const +#endif +{ + while ( begin != end ) + { + resample( *begin++ ); + } +} + +// --------------------------------------------------------------------------- +// resample (sequence of Partials, with timing envelope) +// --------------------------------------------------------------------------- +//! Resample all Partials in the specified (half-open) range using this +//! Resampler's stored sampling interval, so that the Breakpoints in +//! the Partial envelopes will all lie on a common temporal grid. +//! The Breakpoint times in the resampled Partial will comprise a +//! contiguous sequence of integer multiples of the sampling interval, +//! beginning with the multiple nearest to the Partial's start time and +//! ending with the multiple nearest to the Partial's end time. Resampling +//! is performed in-place. +//! +//! \param begin is the beginning of the range of Partials to resample +//! \param end is (one-past) the end of the range of Partials to resample +//! \param timingEnv is the timing envelope, a map of Breakpoint +//! times in resampled Partials onto parameter sampling +//! instants in the original Partials. +//! +//! If compiled with NO_TEMPLATE_MEMBERS defined, then begin and end +//! must be PartialList::iterators, otherwise they can be any type +//! of iterators over a sequence of Partials. +// +#if ! defined(NO_TEMPLATE_MEMBERS) +template<typename Iter> +void Resampler::resample( Iter begin, Iter end, const LinearEnvelope & timingEnv ) const +#else +inline +void Resampler::resample( PartialList::iterator begin, PartialList::iterator end, + const LinearEnvelope & timingEnv ) const +#endif +{ + while ( begin != end ) + { + resample( *begin++, timingEnv ); + } +} + +// --------------------------------------------------------------------------- +// quantize (sequence of Partials) +// --------------------------------------------------------------------------- +//! Quantize all Partials in the specified (half-open) range. +//! Each Breakpoint in the Partials is replaced by a Breakpoint +//! constructed by resampling the Partial at the nearest +//! integer multiple of the of the resampling interval. +//! +//! \param begin is the beginning of the range of Partials to quantize +//! \param end is (one-past) the end of the range of Partials to quantize +//! +//! If compiled with NO_TEMPLATE_MEMBERS defined, then begin and end +//! must be PartialList::iterators, otherwise they can be any type +//! of iterators over a sequence of Partials. +// +#if ! defined(NO_TEMPLATE_MEMBERS) +template<typename Iter> +void Resampler::quantize( Iter begin, Iter end ) const +#else +inline +void Resampler::quantize( PartialList::iterator begin, PartialList::iterator end ) const +#endif +{ + while ( begin != end ) + { + quantize( *begin++ ); + } +} + + +// --------------------------------------------------------------------------- +// resample (static) +// --------------------------------------------------------------------------- +//! Static member that constructs an instance and applies +//! phase-correct resampling to a sequence of Partials. +//! Construct a Resampler using the specified resampling +//! interval, and use it to channelize a sequence of Partials. +//! +//! \param begin is the beginning of a sequence of Partials to +//! resample. +//! \param end is the end of a sequence of Partials to +//! resample. +//! \param sampleInterval is the resampling interval in seconds, +//! Breakpoint data is computed at integer multiples of +//! sampleInterval seconds. +//! \param denseResampling is a boolean flag indicating that dense +//! resamping (Breakpoint at every integer multiple of the +//! resampling interval) should be performed. If false (the +//! default), sparse resampling (Breakpoints only at multiples +//! of the resampling interval near Breakpoint times in the +//! original Partial) is performed. +//! \throw InvalidArgument if sampleInterval is not positive. +//! +//! If compiled with NO_TEMPLATE_MEMBERS defined, then begin and end +//! must be PartialList::iterators, otherwise they can be any type +//! of iterators over a sequence of Partials. +// +#if ! defined(NO_TEMPLATE_MEMBERS) +template< typename Iter > +void Resampler::resample( Iter begin, Iter end, double sampleInterval, + bool denseResampling ) +#else +inline +void Resampler::resample( PartialList::iterator begin, PartialList::iterator end, + double sampleInterval, bool denseResampling ) +#endif +{ + Resampler instance( sampleInterval ); + + if ( denseResampling ) + { + instance.resample( begin, end ); + } + else + { + instance.quantize( begin, end ); + } +} + +} // end of namespace Loris + +#endif /* ndef INCLUDE_RESAMPLER_H */ + |