Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members

Distiller.h

00001 #ifndef INCLUDE_DISTILLER_H
00002 #define INCLUDE_DISTILLER_H
00003 /*
00004  * This is the Loris C++ Class Library, implementing analysis, 
00005  * manipulation, and synthesis of digitized sounds using the Reassigned 
00006  * Bandwidth-Enhanced Additive Sound Model.
00007  *
00008  * Loris is Copyright (c) 1999-2004 by Kelly Fitz and Lippold Haken
00009  *
00010  * This program is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2 of the License, or
00013  * (at your option) any later version.
00014  *
00015  * This program is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY, without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00018  * GNU General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU General Public License
00021  * along with this program; if not, write to the Free Software
00022  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00023  *
00024  *
00025  * Distiller.h
00026  *
00027  * Definition of class Distiller.
00028  *
00029  * Kelly Fitz, 20 Oct 1999
00030  * loris@cerlsoundgroup.org
00031  *
00032  * http://www.cerlsoundgroup.org/Loris/
00033  *
00034  */
00035 
00036 #include "Partial.h"
00037 #include "PartialList.h"
00038 #include "PartialUtils.h"
00039 
00040 #include <algorithm>
00041 
00042 //  begin namespace
00043 namespace Loris {
00044 
00045 // ---------------------------------------------------------------------------
00046 //  class Distiller
00047 //
00071 //
00072 class Distiller
00073 {
00074 //  -- instance variables --
00075 
00076     double _fadeTime, _gapTime;         // distillation parameters
00077         
00078 //  -- public interface --
00079 public:
00080 //  -- construction --
00081 
00102     explicit
00103     Distiller( double partialFadeTime = 0.001    /* 1 ms */,
00104               double partialSilentTime = 0.0001 /* .1 ms */ );
00105      
00106     //  Use compiler-generated copy, assign, and destroy.
00107     
00108 //  -- distillation --
00109 
00136 #if ! defined(NO_TEMPLATE_MEMBERS)
00137     template< typename Container >
00138     typename Container::iterator distill( Container & partials );
00139 #else
00140     inline
00141     PartialList::iterator distill( PartialList & partials );
00142 #endif
00143 
00145 #if ! defined(NO_TEMPLATE_MEMBERS)
00146     template< typename Container >
00147     typename Container::iterator operator() ( Container & partials );
00148 #else
00149     PartialList::iterator operator() ( PartialList & partials );
00150 #endif
00151     
00174    #if ! defined(NO_TEMPLATE_MEMBERS)
00175     template< typename Container >
00176     static typename Container::iterator 
00177     distill( Container & partials, double partialFadeTime,
00178                                   double partialSilentTime = 0.0001 /* .1 ms */ );
00179 #else
00180     static inline PartialList::iterator
00181     distill( PartialList & partials, double partialFadeTime,
00182                                     double partialSilentTime = 0.0001 /* .1 ms */ );
00183 #endif
00184 
00185 
00186 private:
00187 
00188 //  -- helpers --
00189 
00195     void distillOne( PartialList & partials, Partial::label_type label,
00196                      PartialList & distilled );
00197 
00203     void collateUnlabeled( PartialList & unlabled, Partial::label_type startLabel );
00204     
00205 };  //  end of class Distiller
00206 
00207 // ---------------------------------------------------------------------------
00208 //  distill
00209 // ---------------------------------------------------------------------------
00235 //
00236 #if ! defined(NO_TEMPLATE_MEMBERS)
00237 template< typename Container >
00238 typename Container::iterator Distiller::distill( Container & partials )
00239 #else
00240 inline
00241 PartialList::iterator Distiller::distill( PartialList & partials )
00242 #endif
00243 {
00244 #if ! defined(NO_TEMPLATE_MEMBERS)
00245     typedef typename Container::iterator Iterator;
00246 #else
00247     typedef PartialList::iterator Iterator;
00248 #endif
00249 
00250     // Container::iterator dist_begin = partials.begin();
00251     // Container::iterator dist_end = partials.end();
00252     //
00253     //  Using these iterators (as arguments) only makes sense
00254     //  if distill is changed to return the end of the collated
00255     //  Partials, rather than the end of the distilled Partials.
00256     //  In the current implementation, when there are collated
00257     //  Partials, there is no way to find the end of the range 
00258     //  of collated Partials after the call to distill, for 
00259     //  all containers. Making the distill function generic to
00260     //  all containers will work, but making it work on ranges
00261     //  requires an interface change.
00262     
00263     
00264     PartialList distilled, savezeros; //  temporary containers of Partials
00265                   
00266     //  remember the largest label ever used
00267     //  in distilling, collated unlabeled Partials
00268     //  will be assigned labels greater than this:
00269     Partial::label_type maxlabel = 0;
00270     
00271     Iterator lower = partials.begin();
00272     while ( lower != partials.end() )
00273     {
00274         Partial::label_type label = lower->label();
00275 
00276         //  identify the range of Partials having the same label:
00277         Iterator upper = 
00278             std::partition( lower, partials.end(),
00279                             PartialUtils::isLabelEqual( label ) );
00280                             
00281         //  upper is the first Partial after lower whose label is not
00282         //  equal to that of lower.
00283         
00284         //  [lowerbound, upperbound) is a range of all the
00285         //  partials in dist_list labeled label.
00286         //
00287         //  distill labeled channel, unless label is 0
00288         //  (zero-labeled Partials will remain where they
00289         //  are, and wind up at the front of the list): 
00290         if ( label != 0 )
00291         {
00292             maxlabel = std::max( label, maxlabel );
00293             
00294             //  make a container of the Partials having the same 
00295             //  label, and distill them:
00296             PartialList samelabel( lower, upper );
00297             distillOne( samelabel, label, distilled );
00298         }
00299         else    //  label == 0
00300         {
00301             //  save zero-labeled Partials to splice
00302             //  back into the original list
00303             savezeros.insert( savezeros.begin(), lower, upper );
00304         }
00305 
00306         lower = upper;
00307     }
00308         
00309     //  copy the distilled Partials back into the source container,
00310     //  enddistilled is the end of the range of distilled Partials
00311     //  (return this to caller):
00312     Iterator enddistilled =
00313         std::copy( distilled.begin(), distilled.end(), partials.begin() );
00314     
00315     //  append collated unlabeled Partials, if any,
00316     //  and remove extra Partials from the end of the 
00317     //  source collection:
00318     if ( savezeros.empty() )
00319     {
00320         //  remove extra Partials from the end of the source container,
00321         //  update enddistilled, which may become invalid by
00322         //  erasure:
00323         enddistilled = partials.erase( enddistilled, partials.end() );
00324     }
00325     else
00326     {
00327         //  collate unlabeled (zero-labeled) Partials:
00328         collateUnlabeled( savezeros, std::max( maxlabel+1, 1 ) );
00329 
00330         //  copy the collated Partials back into the source container
00331         //  after the range of distilled Partials       
00332         //  (enddistilled is still the end of the distilled Partials):
00333         Iterator endcollated = 
00334             std::copy( savezeros.begin(), savezeros.end(), enddistilled );
00335 
00336         //  remove extra Partials from the end of the source container
00337         //  (enddistilled is still the end of the distilled Partials,
00338         //  because it is the position of the first collate Partial, and
00339         //  there is at least one collated Partial):
00340         partials.erase( endcollated, partials.end() );
00341     }
00342     
00343     return enddistilled;
00344 }
00345 
00346 // ---------------------------------------------------------------------------
00347 //  Function call operator 
00348 // ---------------------------------------------------------------------------
00352 //
00353 #if ! defined(NO_TEMPLATE_MEMBERS)
00354 template< typename Container >
00355 typename Container::iterator Distiller::operator()( Container & partials )
00356 #else
00357 inline
00358 PartialList::iterator Distiller::operator()( PartialList & partials )
00359 #endif
00360 { 
00361     return distill( partials );
00362 }
00363 
00364 // ---------------------------------------------------------------------------
00365 //  distill
00366 // ---------------------------------------------------------------------------
00389 //
00390 #if ! defined(NO_TEMPLATE_MEMBERS)
00391 template< typename Container >
00392 typename Container::iterator 
00393 Distiller::distill( Container & partials, double partialFadeTime,
00394                                           double partialSilentTime )
00395 #else
00396 inline
00397 PartialList::iterator 
00398 Distiller::distill( PartialList & partials, double partialFadeTime,
00399                                             double partialSilentTime )
00400 #endif
00401 {
00402     Distiller instance( partialFadeTime, partialSilentTime );
00403     return instance.distill( partials );
00404 }
00405 
00406 }   //  end of namespace Loris
00407 
00408 #endif /* ndef INCLUDE_DISTILLER_H */

Generated on Thu Apr 14 22:01:55 2005 for Loris by doxygen 1.3.4