From d6073e01c933c77f1e2bc3c3fe1126d617003549 Mon Sep 17 00:00:00 2001 From: John Glover Date: Fri, 8 Jul 2011 18:06:21 +0100 Subject: Start adding Loris files --- src/loris/Distiller.h | 370 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 370 insertions(+) create mode 100644 src/loris/Distiller.h (limited to 'src/loris/Distiller.h') diff --git a/src/loris/Distiller.h b/src/loris/Distiller.h new file mode 100644 index 0000000..f1672ce --- /dev/null +++ b/src/loris/Distiller.h @@ -0,0 +1,370 @@ +#ifndef INCLUDE_DISTILLER_H +#define INCLUDE_DISTILLER_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 + * + * + * Distiller.h + * + * Definition of class Distiller. + * + * Kelly Fitz, 20 Oct 1999 + * loris@cerlsoundgroup.org + * + * http://www.cerlsoundgroup.org/Loris/ + * + */ + +#include "Partial.h" +#include "PartialList.h" +#include "PartialUtils.h" + +#include "Notifier.h" // for debugging only + +#include + +// begin namespace +namespace Loris { + +// --------------------------------------------------------------------------- +// class Distiller +// +//! Class Distiller represents an algorithm for "distilling" a group of +//! Partials that logically represent a single component into a single +//! Partial. +//! +//! The sound morphing algorithm in Loris requires that Partials in a +//! given source be labeled uniquely, that is, no two Partials can have +//! the same label. The Distiller enforces this condition. All Partials +//! identified with a particular frequency channel (see Channelizer), and, +//! therefore, having a common label, are distilled into a single Partial, +//! leaving at most a single Partial per frequency channel and label. +//! Channels that contain no Partials are not represented in the distilled +//! data. Partials that are not labeled, that is, Partials having label 0, +//! are are left unmodified at the end of the Partial sequence. +//! +//! Distillation modifies the Partial container (a PartialList). All +//! Partials in the distilled range having a common label are replaced by +//! a single Partial in the distillation process. Only labeled +//! Partials are affected by distillation. +// +class Distiller +{ +// -- instance variables -- + + double _fadeTime, _gapTime; // distillation parameters + +// -- public interface -- +public: + +// -- global defaults and constants -- + + enum + { + + //! Default time in milliseconds over which Partials joined by + //! distillation fade to and from zero amplitude. Divide by + //! 1000 to use as a member function parameter. This parameter + //! should be the same in Distiller, Sieve, and Collator. + DefaultFadeTimeMs = 5, + + //! Default minimum duration in milliseconds of the silent + //! (zero-amplitude) gap between two Partials joined by + //! distillation. Divide by 1000 to use as a member function + //! parameter. This parameter should be the same in Distiller, + //! Sieve, and Collator. + DefaultSilentTimeMs = 1 + }; + +// -- construction -- + + //! Construct a new Distiller using the specified fade time + //! for gaps between Partials. When two non-overlapping Partials + //! are distilled into a single Partial, the distilled Partial + //! fades out at the end of the earlier Partial and back in again + //! at the onset of the later one. The fade time is the time over + //! which these fades occur. By default, use a 1 ms fade time. + //! The gap time is the additional time over which a Partial faded + //! out must remain at zero amplitude before it can fade back in. + //! By default, use a gap time of one tenth of a millisecond, to + //! prevent a pair of arbitrarily close null Breakpoints being + //! inserted. + //! + //! \param partialFadeTime is the time (in seconds) over + //! which Partials joined by distillation fade to + //! and from zero amplitude. (Default is + //! Distiller::DefaultFadeTime). + //! \param partialSilentTime is the minimum duration (in seconds) + //! of the silent (zero-amplitude) gap between two + //! Partials joined by distillation. (Default is + //! Distiller::DefaultSilentTime). + explicit + Distiller( double partialFadeTime = Distiller::DefaultFadeTimeMs/1000.0, + double partialSilentTime = Distiller::DefaultSilentTimeMs/1000.0 ); + + // Use compiler-generated copy, assign, and destroy. + +// -- distillation -- + + //! Distill labeled Partials in a collection leaving only a single + //! Partial per non-zero label. + //! + //! Unlabeled (zero-labeled) Partials are left unmodified at + //! the end of the distilled Partials. + //! + //! Return an iterator refering to the position of the first unlabeled Partial, + //! or the end of the distilled collection if there are no unlabeled Partials. + //! Since distillation is in-place, the Partials collection may be smaller + //! (fewer Partials) after distillation, and any iterators on the collection + //! may be invalidated. + //! + //! \post All labeled Partials in the collection are uniquely-labeled, + //! and all unlabeled Partials have been moved to the end of the + //! sequence. + //! \param partials is the collection of Partials to distill in-place + //! \return the position of the end of the range of distilled Partials, + //! which is either the end of the collection, or the position + //! or the first unlabeled Partial. + //! + //! If compiled with NO_TEMPLATE_MEMBERS defined, then partials + //! must be a PartialList, otherwise it can be any container type + //! storing Partials that supports at least bidirectional iterators. + //! + //! \sa Distiller::distill( Container & partials ) +#if ! defined(NO_TEMPLATE_MEMBERS) + template< typename Container > + typename Container::iterator distill( Container & partials ); +#else + inline + PartialList::iterator distill( PartialList & partials ); +#endif + + //! Function call operator: same as distill( PartialList & partials ). +#if ! defined(NO_TEMPLATE_MEMBERS) + template< typename Container > + typename Container::iterator operator() ( Container & partials ); +#else + PartialList::iterator operator() ( PartialList & partials ); +#endif + + //! Static member that constructs an instance and applies + //! it to a sequence of Partials. + //! + //! \post All labeled Partials in the collection are uniquely-labeled, + //! and all unlabeled Partials have been moved to the end of the + //! sequence. + //! \param partials is the collection of Partials to distill in-place + //! \param partialFadeTime is the time (in seconds) over + //! which Partials joined by distillation fade to + //! and from zero amplitude. + //! \param partialSilentTime is the minimum duration (in seconds) + //! of the silent (zero-amplitude) gap between two + //! Partials joined by distillation. (Default is + //! Distiller::DefaultSilentTime). + //! \return the position of the end of the range of distilled Partials, + //! which is either the end of the collection, or the position + //! or the first unlabeled Partial. + //! + //! If compiled with NO_TEMPLATE_MEMBERS defined, then partials + //! must be a PartialList, otherwise it can be any container type + //! storing Partials that supports at least bidirectional iterators. +#if ! defined(NO_TEMPLATE_MEMBERS) + template< typename Container > + static typename Container::iterator + distill( Container & partials, double partialFadeTime, + double partialSilentTime = DefaultSilentTimeMs/1000.0 ); +#else + static inline PartialList::iterator + distill( PartialList & partials, double partialFadeTime, + double partialSilentTime = DefaultSilentTimeMs/1000.0 ); +#endif + +private: + +// -- helpers -- + + //! Distill labeled Partials in a PartialList leaving only a single + //! Partial per non-zero label. + //! + //! Unlabeled (zero-labeled) Partials are left unmodified at + //! the end of the distilled Partials. + //! + //! Return an iterator refering to the position of the first unlabeled Partial, + //! or the end of the distilled collection if there are no unlabeled Partials. + //! Since distillation is in-place, the Partials collection may be smaller + //! (fewer Partials) after distillation, and any iterators on the collection + //! may be invalidated. + //! + //! \post All labeled Partials in the collection are uniquely-labeled, + //! and all unlabeled Partials have been moved to the end of the + //! sequence. + //! \param partials is the collection of Partials to distill in-place + //! \return the position of the end of the range of distilled Partials, + //! which is either the end of the collection, or the position + //! or the first unlabeled Partial. + PartialList::iterator distill_list( PartialList & partials ); + + //! Distill a list of Partials having a common label + //! into a single Partial with that label, and append it + //! to the distilled collection. If an empty list of Partials + //! is passed, then an empty Partial having the specified + //! label is appended. + void distillOne( PartialList & partials, Partial::label_type label, + PartialList & distilled ); + +}; // end of class Distiller + +// --------------------------------------------------------------------------- +// distill +// --------------------------------------------------------------------------- +//! Distill labeled Partials in a collection leaving only a single +//! Partial per non-zero label. +//! +//! Unlabeled (zero-labeled) Partials are left unmodified at +//! the end of the distilled Partials. +//! +//! Return an iterator refering to the position of the first unlabeled Partial, +//! or the end of the distilled collection if there are no unlabeled Partials. +//! Since distillation is in-place, the Partials collection may be smaller +//! (fewer Partials) after distillation, and any iterators on the collection +//! may be invalidated. +//! +//! \post All labeled Partials in the collection are uniquely-labeled, +//! and all unlabeled Partials have been moved to the end of the +//! sequence. +//! \param partials is the collection of Partials to distill in-place +//! \return the position of the end of the range of distilled Partials, +//! which is either the end of the collection, or the position +//! or the first unlabeled Partial. +//! +//! If compiled with NO_TEMPLATE_MEMBERS defined, then partials +//! must be a PartialList, otherwise it can be any container type +//! storing Partials that supports at least bidirectional iterators. +//! +// +#if ! defined(NO_TEMPLATE_MEMBERS) +template< typename Container > +typename Container::iterator Distiller::distill( Container & partials ) +{ + // This can be done so much more easily and + // efficiently on a list than on other containers + // that it is worth copying the Partials to a + // list for distillation, and then transfering + // them back. + // + // See below for a specialization for the case + // of the Container being a list, so no copy + // is needed. + PartialList pl( partials.begin(), partials.end() ); + PartialList::iterator it = distill_list( pl ); + + // pl has distilled Partials at beginning, and + // unlabeled Partials at end: + typename Container::iterator beginUnlabeled = + std::copy( pl.begin(), it, partials.begin() ); + + typename Container::iterator endUnlabeled = + std::copy( it, pl.end(), beginUnlabeled ); + + + partials.erase( endUnlabeled, partials.end() ); + + return beginUnlabeled; +} + +// specialization for PartialList container +template< > +inline +PartialList::iterator Distiller::distill( PartialList & partials ) +{ + debugger << "using PartialList version of distill to avoid copying" << endl; + return distill_list( partials ); +} +#else +inline +PartialList::iterator Distiller::distill( PartialList & partials ) +{ + return distill_list( partials ); +} +#endif + +// --------------------------------------------------------------------------- +// Function call operator +// --------------------------------------------------------------------------- +//! Function call operator: same as distill( PartialList & partials ). +//! +//! \sa Distiller::distill( Container & partials ) +// +#if ! defined(NO_TEMPLATE_MEMBERS) +template< typename Container > +typename Container::iterator Distiller::operator()( Container & partials ) +#else +inline +PartialList::iterator Distiller::operator()( PartialList & partials ) +#endif +{ + return distill( partials ); +} + +// --------------------------------------------------------------------------- +// distill +// --------------------------------------------------------------------------- +//! Static member that constructs an instance and applies +//! it to a sequence of Partials. +//! +//! \post All labeled Partials in the collection are uniquely-labeled, +//! and all unlabeled Partials have been moved to the end of the +//! sequence. +//! \param partials is the collection of Partials to distill in-place +//! \param partialFadeTime is the time (in seconds) over +//! which Partials joined by distillation fade to +//! and from zero amplitude. +//! \param partialSilentTime is the minimum duration (in seconds) +//! of the silent (zero-amplitude) gap between two +//! Partials joined by distillation. (Default is +//! Distiller::DefaultSilentTime). +//! \return the position of the end of the range of distilled Partials, +//! which is either the end of the collection, or the position +//! or the first unlabeled Partial. +//! +//! If compiled with NO_TEMPLATE_MEMBERS defined, then partials +//! must be a PartialList, otherwise it can be any container type +//! storing Partials that supports at least bidirectional iterators. +// +#if ! defined(NO_TEMPLATE_MEMBERS) +template< typename Container > +typename Container::iterator +Distiller::distill( Container & partials, double partialFadeTime, + double partialSilentTime ) +#else +inline +PartialList::iterator +Distiller::distill( PartialList & partials, double partialFadeTime, + double partialSilentTime ) +#endif +{ + Distiller instance( partialFadeTime, partialSilentTime ); + return instance.distill( partials ); +} + +} // end of namespace Loris + +#endif /* ndef INCLUDE_DISTILLER_H */ -- cgit v1.2.3