// ---------------------------------------------------------------------------
//	distillOne
// ---------------------------------------------------------------------------
//	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 Distiller::distillOne( PartialList & partials, Partial::label_type label,
                            PartialList & distilled )
{
	debugger << "Distiller found " << partials.size() 
			 << " Partials labeled " << label << endl;

	Partial newp;
    newp.setLabel( label );

    if ( partials.size() == 1 )
    {
        //  trivial if there is only one partial to distill
        newp = partials.front();
    }
	else if ( partials.size() > 0 )  //  it will be an empty Partial otherwise
    {	
    	//	sort Partials by duration, longer
    	//	Partials will be prefered:
    	partials.sort( distillSorter );
    	
    	// keep the longest Partial:
    	PartialList::iterator it = partials.begin();
    	newp = *it;
    	fadeInAndOut( newp, _fadeTime );
        	
    	//	Iterate over remaining Partials:
    	for ( ++it; it != partials.end(); ++it )
    	{            
            fadeInAndOut( *it, _fadeTime );
            
    		std::pair< Partial::iterator, Partial::iterator > range = 
    			findContribution( *it, newp, _fadeTime, _gapTime );
    		Partial::iterator cb = range.first, ce = range.second;

            //  There can only be one contributing regions because
            //  (and only because) the partials are sorted by length
            //  first!
    		
    		//	merge Breakpoints into the new Partial, if
    		//	there are any that contribute, otherwise
    		//	just absorb the current Partial as noise:
    		if ( cb != ce )
    		{
    			//	absorb the non-contributing part:
    			if ( ce != it->end() )
    			{
    				Partial absorbMe( --Partial::iterator(ce), it->end() );
    				    //  shouldn't this just be ce?
    				newp.absorb( absorbMe );
    			
                    //	There cannot be a non-contributing part
                    //	at the beginning of the Partial too, because
                    //  we always retain the beginning of the Partial.
                    //  If findContribution were changed, then 
                    //  we might also want to absorb the beginning.
                    //
    				// Partial absorbMeToo( it->begin(), cb );
    				// newp.absorb( absorbMeToo );
    			}

    			// merge the contributing part:
    			merge( cb, ce, newp, _fadeTime, _gapTime );
    		}
    		else
    		{
    			//	no contribution, absorb the whole thing:
    			newp.absorb( *it );
    		}		
    	}
    }	

    //  take the null Breakpoints off the ends
    //  should check whether this is appropriate?
    if ( 0 == newp.begin().breakpoint().amplitude() )
    {
        newp.erase( newp.begin() );
    }
    
    Partial::iterator lastBpPos = --(Partial::iterator(newp.end()));
    if ( 0 == lastBpPos.breakpoint().amplitude() )
    {
        newp.erase( lastBpPos );
    }
    
    //  insert the new Partial in the distilled collection 
    //  in label order:
    distilled.insert( std::lower_bound( distilled.begin(), distilled.end(), 
                                        newp, 
                                        PartialUtils::compareLabelLess() ),
                      newp );
}