Example #1
0
// ---------------------------------------------------------------------------
//	construction
// ---------------------------------------------------------------------------
//!	Construct a new fundamental FrequencyReference derived from the 
//!	specified half-open (STL-style) range of Partials that lies
//!	within the speficied average frequency range. Construct the 
//!	reference envelope with approximately numSamps points.
//!
//! \param	begin The beginning of a range of Partials from which to
//!			construct a frequency refence envelope.
//! \param	end The end of a range of Partials from which to
//!			construct a frequency refence envelope.
//!	\param	minFreq The minimum expected fundamental frequency.
//! \param	maxFreq The maximum expected fundamental frequency.
//! \param	numSamps The approximate number of estimate of the 
//!			fundamental frequency from which to construct the 
//!			frequency reference envelope.
//
FrequencyReference::FrequencyReference( PartialList::const_iterator begin, 
										PartialList::const_iterator end, 
										double minFreq, double maxFreq,
										long numSamps ) :
	_env( new LinearEnvelope() )
{
	if ( numSamps < 1 )
	{
		Throw( InvalidArgument, "A frequency reference envelope must have a positive number of samples." );
    }
    
	//	sanity:
	if ( maxFreq < minFreq )
	{
		std::swap( minFreq, maxFreq );
    }
    
#ifdef Loris_Debug
	debugger << "Finding frequency reference envelope in range " <<
	debugger << minFreq << " to " << maxFreq << " Hz, from " <<
	debugger << std::distance(begin,end) << " Partials" << std::endl;
#endif

	
	FundamentalFromPartials est = createEstimator();
	std::pair< double, double > span = PartialUtils::timeSpan( begin, end );
	double dt = ( span.second - span.first ) / ( numSamps + 1 );
	*_env = est.buildEnvelope( begin, end, 
                               span.first, span.second, dt,
                               minFreq, maxFreq,
                               Confidence );
}
Example #2
0
// ---------------------------------------------------------------------------
//	construction
// ---------------------------------------------------------------------------
//!	Construct a new fundamental FrequencyReference derived from the 
//!	specified half-open (STL-style) range of Partials that lies
//!	within the speficied average frequency range. Construct the 
//!	reference envelope from fundamental estimates taken every
//! five milliseconds.
//!
//! \param	begin The beginning of a range of Partials from which to
//!			construct a frequency refence envelope.
//! \param	end The end of a range of Partials from which to
//!			construct a frequency refence envelope.
//!	\param	minFreq The minimum expected fundamental frequency.
//! \param	maxFreq The maximum expected fundamental frequency.
//
FrequencyReference::FrequencyReference( PartialList::const_iterator begin, 
										PartialList::const_iterator end, 
										double minFreq, double maxFreq ) :
	_env( new LinearEnvelope() )
{
	//	sanity:
	if ( maxFreq < minFreq )
	{
		std::swap( minFreq, maxFreq );
	}
	
#ifdef Loris_Debug
	debugger << "Finding frequency reference envelope in range " <<
	debugger << minFreq << " to " << maxFreq << " Hz, from " <<
	debugger << std::distance(begin,end) << " Partials" << std::endl;
#endif
    
	FundamentalFromPartials est = createEstimator();
	std::pair< double, double > span = PartialUtils::timeSpan( begin, end );
	*_env = est.buildEnvelope( begin, end, 
                               span.first, span.second, Interval,
                               minFreq, maxFreq,
                               Confidence );
    
}
int main( int argc, char * argv[] )
{
    std::cout << "Unit test for fundamental estimation functions." << endl;
    std::cout << "Tests FundamentalFromPartials and FundamentalFromSamples." << endl << endl;
    std::cout << "Relies on AiffFile, Analyzer, Partial, PartialList, and LinearEnvelope." << endl << endl;
    std::cout << "Built: " << __DATE__ << endl << endl;

	string path(""); 
	if ( std::getenv("srcdir") ) 
	{
		path = std::getenv("srcdir");
		path = path + "/";
	}
    
    //  --- parameters that are sample-specific ---
    string fname = path + "clarinet.aiff";
    double fmin = 200;
    double fmax = 500;
    double res = 415*.8;
    double win = 415*1.6;
    double interval = 0.05;  //  50 ms
    
    const double approx = 414;
    
    double x;
    
    try
        {
        //  import (mono) samples        
        std::vector< double > buf;
        double rate;
        importSamples( fname, buf, &rate );


        //  step 1. analyze the samples    
        Analyzer anal( res, win );
        anal.buildFundamentalEnv( fmin, fmax );
        anal.setHopTime( interval );
        cout << "--- step 1 analyzer ---" << endl;
        cout << "analysis resolution is " << anal.freqResolution() << endl;
        cout << "window width is " << anal.windowWidth() << endl;
        cout << "amplitude threshold is " << anal.ampFloor() << endl;    
        cout << "lower bound is " << fmin << endl;
        cout << "upper bound is " << fmax << endl;
                
        PartialList plist = anal.analyze( buf, rate );
        LinearEnvelope est1 = anal.fundamentalEnv();

        x = dumpEnvelope( est1 );
        if ( (approx-1) > x || (approx+1) < x )
        {
            throw std::runtime_error( "that isn't right" );
        }
        
        double tbeg = est1.begin()->first;
        double tend = (--est1.end())->first;
        
        //  step 2. estimate fundamental from Partials
        FundamentalFromPartials eparts;
        eparts.setAmpFloor( -65 );
        eparts.setAmpRange( 40 );
        eparts.setFreqCeiling( 5000 );
        
        cout << "--- step 2 fundamental estimator from partials ---" << endl;
        cout << "amplitude threshold is " << eparts.ampFloor() << endl;
        cout << "amplitude range is " << eparts.ampRange() << endl;
        cout << "frequency ceiling is " << eparts.freqCeiling() << endl;
        cout << "precision level is " << eparts.precision() << " Hz" << endl;
        
        LinearEnvelope est2 = eparts.buildEnvelope( plist, tbeg, tend, 
                                                    interval, fmin, fmax, 0.95 );
        x = dumpEnvelope( est2 );
        if ( (approx-1) > x || (approx+1) < x )
        {
            throw std::runtime_error( "that isn't right" );
        }
                
        //  step 3. estimate fundamental from the samples    
        FundamentalFromSamples esamps( win );
        esamps.setAmpFloor( -65 );
        esamps.setAmpRange( 40 );
        esamps.setFreqCeiling( 5000 );
        
        cout << "--- step 3 fundamental estimator from samples ---" << endl;
        cout << "window width is " << esamps.windowWidth() << endl;
        cout << "amplitude threshold is " << esamps.ampFloor() << endl;
        cout << "amplitude range is " << esamps.ampRange() << endl;
        cout << "frequency ceiling is " << esamps.freqCeiling() << endl;
        cout << "precision level is " << esamps.precision() << " Hz" << endl;

        LinearEnvelope est3 = esamps.buildEnvelope( buf, rate, tbeg, tend, 
                                                    interval, fmin, fmax, 0.95 );
        x = dumpEnvelope( est3 );
        if ( (approx-1) > x || (approx+1) < x )
        {
            throw std::runtime_error( "that isn't right" );
        }
        
    }
    catch( Exception & ex ) 
    {
        cout << "Caught Loris exception: " << ex.what() << endl;
        return 1;
    }
    catch( std::exception & ex ) 
    {
        cout << "Caught std C++ exception: " << ex.what() << endl;
        return 1;
    }   
    
    //  return successfully
    cout << "Fundamental estimation passed all tests." << endl;
    return 0;

    return 0;
}