// ---------------------------------------------------------------------------
//	distillSorter (static helper)
// ---------------------------------------------------------------------------
//  Helper for sorting Partials for distilling.
//
static bool distillSorter( const Partial & lhs, const Partial & rhs )
{
    double ldur = lhs.duration(), rdur = rhs.duration();
    if ( ldur != rdur )
    {        
        return ldur > rdur;      
    }
    else
    {
        //  What to do for same-duration Partials?
        //  Need to do something consistent, should look
        //  for energy?
        return lhs.startTime() < rhs.startTime();
        /*
        double lpeak = PartialUtils::peakAmp( lhs );
        double rpeak = PartialUtils::peakAmp( rhs );
        return lhs > rhs;
        */
    }
}
Beispiel #2
0
Iter
find_overlapping( Partial & p, double minGapTime, Iter start, Iter end)
{
	for ( Iter it = start; it != end; ++it ) 
	{
		//	skip if other partial is already sifted out.
		if ( (*it)->label() == 0 )
			continue;
		
		//	skip the source Partial:
		//	(identity test: compare addresses)
		//	(this is a sanity check, should not happen since
		//	src should be at position end)
		Assert( (*it) != &p );

		//  test for overlap:
		if ( p.startTime() < (*it)->endTime() + minGapTime &&
			 p.endTime() + minGapTime > (*it)->startTime() )
		{
			//  Does the overlapping Partial have longer duration?
			//	(this should never be true, since the Partials
			//	are sorted by duration)
			Assert( p.duration() <= (*it)->duration() );
			
#if Debug_Loris
			debugger << "Partial starting " << p.startTime() << ", " 
					 << p.begin().breakpoint().frequency() << " ending " 
					 << p.endTime()  << ", " << (--p.end()).breakpoint().frequency() 
					 << " zapped by overlapping Partial starting " 
					 << (*it)->startTime() << ", " << (*it)->begin().breakpoint().frequency()
					 << " ending " << (*it)->endTime() << ", " 
					 << (--(*it)->end()).breakpoint().frequency()  << endl;
#endif
			return it;
		}
	}
	
	//	no overlapping Partial found:
	return end;
}
// ---------------------------------------------------------------------------
//	getPartial
// ---------------------------------------------------------------------------
//	Convert any FileIOExceptions into ImportExceptions, so that clients can 
//	reasonably expect to catch only ImportExceptions.
//
static void
getPartial( std::istream & s, PartialList & partials, double bweCutoff )
{
	try 
	{
		//	read the Track header:
		TrackOnDisk tkHeader;
		readTrackHeader( s, tkHeader );
		
		//	create a Partial:
		Partial p;
		p.setLabel( tkHeader.label );
		
		//	keep running phase and time for Breakpoint construction:
		double phase = tkHeader.initialPhase;
		
		//	convert time to seconds and offset by a millisecond to 
		//	allow for implied onset (Lemur analysis data was shifted
		//	such that the earliest Partial starts at 0).
		double time = tkHeader.startTime * 0.001;	
		
		//	use this to compute phases:
		double prevTtnSec = 0.;
		
		//	loop: read Peak, create Breakpoint, add to Partial:
		for ( int i = 0; i < tkHeader.numPeaks; ++i ) {
			//	read Peak:
			PeakOnDisk pkData;
			readPeakData( s, pkData );
			
			double frequency = pkData.frequency;
			double amplitude = pkData.magnitude;
			double bandwidth = std::min( pkData.bandwidth, 1.f );
			
			//	fix bandwidth:
			//	Lemur used a cutoff frequency, below which 
			//	bandwidth was ignored; Loris does not, so 
			//	toss out that bogus bandwidth.
			if ( frequency < bweCutoff ) {
				amplitude *= std::sqrt(1. - bandwidth);
				bandwidth = 0.;
			}
			//	otherwise, adjust the bandwidth value
			//	to account for the difference in noise
			//	scaling between Lemur and Loris; this
			//	mess doubles the noise modulation index
			//	without changing the sine modulation index,
			//	see Oscillator::modulate(). 
			else {
				amplitude *= std::sqrt( 1. + (3. * bandwidth) );
				bandwidth = (4. * bandwidth) / ( 1. + (3. * bandwidth) ); 
			}

			//	update phase based on _this_ pkData's interpolated freq:
			phase +=2. * Pi * prevTtnSec * pkData.interpolatedFrequency;
			phase = std::fmod( phase, 2. * Pi );
			
			//	create Breakpoint:	
			Breakpoint bp( frequency, amplitude, bandwidth, phase );
			
			//	insert in Partial:
			p.insert( time, bp );
			
			//	update time:
			prevTtnSec = pkData.ttn * 0.001;
			time += prevTtnSec;
		}

		if ( p.duration() > 0. ) {
			partials.push_back( p );
		}
		/*
		else {
			debugger << "import rejecting a Partial of zero duration (" 
					<< tkHeader.numPeaks << " peaks read)" << endl;
		}
		*/
	}
	catch( FileIOException & ex ) {
		ex.append(  "Failed to import a partial from a Lemur file." );
		throw;
	}
	
}