Exemple #1
0
std::vector<typename Partial::SolutionT> generatePar(int depth, Partial const & part, Constraint constr)
{
    using SolutionVec = std::vector<typename Partial::SolutionT>;

    if (depth == 0)
    {
        return generate(part, constr);
    }
    else if (part.isFinished(constr))
    {
        SolutionVec result{ part.getSolution() };
        return result;
    }
    else
    {
        Stream<Partial> partList = part.refine(constr);

        std::vector<std::future<SolutionVec>> futResult;
        forEach(std::move(partList), [&constr, &futResult, depth](Partial const & part)
        {
            std::future<SolutionVec> futLst =
                std::async([constr, part, depth]() {
                return generatePar(depth - 1, part, constr);
            });
            futResult.push_back(std::move(futLst));
        });
        std::vector<SolutionVec> all = when_all_vec(futResult);
        return concatAll(all);
    }
}
Exemple #2
0
// ---------------------------------------------------------------------------
//    harmonify
// ---------------------------------------------------------------------------
//! Apply the reference envelope to a Partial.
//!
//! \pre    The Partial p must be labeled with its harmonic number.
//
void Harmonifier::harmonify( Partial & p ) const
{
    //    compute absolute magnitude thresholds:
    static const double FadeRangeDB = 10;
    const double BeginFade = std::pow( 10., 0.05 * (_freqFixThresholdDb+FadeRangeDB) );
    const double Threshold = std::pow( 10., 0.05 * _freqFixThresholdDb );
    const double OneOverFadeSpan = 1. / ( BeginFade - Threshold );

    double fscale = (double)p.label() / _refPartial.label();
    
    for ( Partial::iterator it = p.begin(); it != p.end(); ++it )
    {
        Breakpoint & bp = it.breakpoint();            
                
        if ( bp.amplitude() < BeginFade )
        {
            //  alpha is the harmonic frequency weighting:
            //  when alpha is 1, the harmonic frequency is used,
            //  when alpha is 0, the breakpoint frequency is
            //  unmodified.
            double alpha = 
                std::min( ( BeginFade - bp.amplitude() ) * OneOverFadeSpan, 1. );
                
            //  alpha is scaled by the weigthing envelope
            alpha *= _weight->valueAt( it.time() );
            
            double fRef = _refPartial.frequencyAt( it.time() );
            
            bp.setFrequency( ( alpha * ( fRef * fscale ) ) + 
                             ( (1 - alpha) * bp.frequency() ) );
        }

    }
}
// ---------------------------------------------------------------------------
//	BandwidthSetter function call operator
// ---------------------------------------------------------------------------
//	Set the bandwidth of the specified Partial according to
//	an envelope representing a time-varying bandwidth value.
//
void 
BandwidthSetter::operator()( Partial & p ) const
{
	for ( Partial::iterator pos = p.begin(); pos != p.end(); ++pos ) 
	{		
		pos.breakpoint().setBandwidth( env->valueAt( pos.time() ) );
	}	
}
bool PartialBuilder::better_match( const Partial & part1, 
                                   const Partial & part2, const SpectralPeak & pk )
{
	Assert( part1.numBreakpoints() > 0 );
	Assert( part2.numBreakpoints() > 0 );
	
	return freq_distance( part1, pk ) < freq_distance( part2, pk );
}	
// ---------------------------------------------------------------------------
//	FrequencyScaler function call operator
// ---------------------------------------------------------------------------
//	Scale the frequency of the specified Partial according to
//	an envelope representing a time-varying frequency scale value.
//
void 
FrequencyScaler::operator()( Partial & p ) const
{
	for ( Partial::iterator pos = p.begin(); pos != p.end(); ++pos ) 
	{		
		pos.breakpoint().setFrequency( pos.breakpoint().frequency() * 
									   env->valueAt( pos.time() ) );
	}	
}
// ---------------------------------------------------------------------------
//	AmplitudeScaler function call operator
// ---------------------------------------------------------------------------
//	Scale the amplitude of the specified Partial according to
//	an envelope representing a time-varying amplitude scale value.
//
void 
AmplitudeScaler::operator()( Partial & p ) const
{
	for ( Partial::iterator pos = p.begin(); pos != p.end(); ++pos ) 
	{		
		pos.breakpoint().setAmplitude( pos.breakpoint().amplitude() * 
									          env->valueAt( pos.time() ) );
	}	
}
// ---------------------------------------------------------------------------
//	fixPhaseBefore
//
//! Recompute phases of all Breakpoints earlier than the specified time 
//! so that the synthesize phases of those earlier Breakpoints matches 
//! the stored phase, and the synthesized phase at the specified
//! time matches the stored (not recomputed) phase.
//! 
//! Backward phase-fixing stops if a null (zero-amplitude) Breakpoint
//! is encountered, because nulls are interpreted as phase reset points
//! in Loris. If a null is encountered, the remainder of the Partial
//! (the front part) is fixed in the forward direction, beginning at
//! the start of the Partial.
//!
//! \param p    The Partial whose phases should be fixed.
//! \param t    The time before which phases should be adjusted.
//
void fixPhaseBefore( Partial & p, double t )
{
    if ( 1 < p.numBreakpoints() )
    {
        Partial::iterator pos = p.findNearest( t );
        Assert( pos != p.end() );

        fixPhaseBackward( p.begin(), pos );
    }
}
// ---------------------------------------------------------------------------
//	freq_distance
// ---------------------------------------------------------------------------
//	Helper function, used in formPartials().
//	Returns the (positive) frequency distance between a Breakpoint 
//	and the last Breakpoint in a Partial.
//
inline double 
PartialBuilder::freq_distance( const Partial & partial, const SpectralPeak & pk )
{
    double normBpFreq = pk.frequency() / mFreqWarping->valueAt( pk.time() );
    
    double normPartialEndFreq = 
        partial.last().frequency() / mFreqWarping->valueAt( partial.endTime() );
    
	return std::fabs( normPartialEndFreq - normBpFreq );
}
// ---------------------------------------------------------------------------
//	PitchShifter function call operator
// ---------------------------------------------------------------------------
//	Shift the pitch of the specified Partial according to 
//	the given pitch envelope. The pitch envelope is assumed to have 
//	units of cents (1/100 of a halfstep).
//
void 
PitchShifter::operator()( Partial & p ) const
{
	for ( Partial::iterator pos = p.begin(); pos != p.end(); ++pos ) 
	{		
		//	compute frequency scale:
		double scale = 
			std::pow( 2., ( 0.01 * env->valueAt( pos.time() ) ) / 12. );				
		pos.breakpoint().setFrequency( pos.breakpoint().frequency() * scale );
	}	
}
Exemple #10
0
// ---------------------------------------------------------------------------
//	peakAmplitude
// ---------------------------------------------------------------------------
//! Return the maximum amplitude achieved by a partial. 
//!  
//! \param  p is the Partial to evaluate
//! \return the maximum (absolute) amplitude achieved by 
//!         the partial p
//
double peakAmplitude( const Partial & p )
{
    double peak = 0;
    for ( Partial::const_iterator it = p.begin();
          it != p.end();
          ++it )
    {
        peak = std::max( peak, it->amplitude() );
    }
    return peak;
}
Exemple #11
0
// ---------------------------------------------------------------------------
//	fixPhaseAfter
//
//! Recompute phases of all Breakpoints later than the specified time 
//! so that the synthesize phases of those later Breakpoints matches 
//! the stored phase, as long as the synthesized phase at the specified
//! time matches the stored (not recomputed) phase.
//! 
//! Phase fixing is only applied to non-null (nonzero-amplitude) Breakpoints,
//! because null Breakpoints are interpreted as phase reset points in 
//! Loris. If a null is encountered, its phase is simply left unmodified,
//! and future phases wil be recomputed from that one.
//!
//! \param p    The Partial whose phases should be fixed.
//! \param t    The time after which phases should be adjusted.
//
void fixPhaseAfter( Partial & p, double t )
{
    //  nothing to do it there are not at least
    //  two Breakpoints in the Partial   
    if ( 1 < p.numBreakpoints() )
    {
        Partial::iterator pos = p.findNearest( t );
        Assert( pos != p.end() );

        fixPhaseForward( pos, --p.end() );
    }
}
Exemple #12
0
bool Poly::startAbort() {
	if (state == POLY_Inactive) {
		return false;
	}
	for (int t = 0; t < 4; t++) {
		Partial *partial = partials[t];
		if (partial != NULL) {
			partial->startAbort();
		}
	}
	return true;
}
// ---------------------------------------------------------------------------
//	fixFrequency
//
//!	Adjust frequencies of the Breakpoints in the 
//! specified Partial such that the rendered Partial 
//!	achieves (or matches as nearly as possible, within 
//!	the constraint of the maximum allowable frequency
//! alteration) the analyzed phases. 
//!
//! This just iterates over the Partial calling
//! matchPhaseFwd, should probably name those similarly.
//!
//!  \param     partial The Partial whose frequencies,
//!             and possibly phases (if the frequencies
//!             cannot be sufficiently altered to match
//!             the phases), will be recomputed.
//!  \param     maxFixPct The maximum allowable frequency 
//!             alteration, default is 0.2%.
//
void fixFrequency( Partial & partial, double maxFixPct )
{	
	if ( partial.numBreakpoints() > 1 )
	{	
		Partial::iterator next = partial.begin();
		Partial::iterator prev = next++;
		while ( next != partial.end() )		
		{
			matchPhaseFwd( prev.breakpoint(), next.breakpoint(), 
						   next.time() - prev.time(), 0.5, maxFixPct );
			prev = next++;
		}
    }
}
Exemple #14
0
bool Poly::startDecay() {
	if (state == POLY_Inactive || state == POLY_Releasing) {
		return false;
	}
	state = POLY_Releasing;

	for (int t = 0; t < 4; t++) {
		Partial *partial = partials[t];
		if (partial != NULL) {
			partial->startDecayAll();
		}
	}
	return true;
}
Exemple #15
0
// ---------------------------------------------------------------------------
//	channelize (one Partial)
// ---------------------------------------------------------------------------
//!	Label a Partial with the number of the frequency channel corresponding to
//!	the average frequency over all the Partial's Breakpoints.
//!	
//!	\param partial is the Partial to label.
//
void
Channelizer::channelize( Partial & partial ) const
{
    using std::pow;

	// debugger << "channelizing Partial with " << partial.numBreakpoints() << " Breakpoints" << endl;
			
	//	compute an amplitude-weighted average channel
	//	label for each Partial:
	//double ampsum = 0.;
	double weightedlabel = 0.;
	Partial::const_iterator bp;
	for ( bp = partial.begin(); bp != partial.end(); ++bp )
	{
				
		double f = bp.breakpoint().frequency();
		double t = bp.time();
		
        double weight = 1;
        if ( 0 != _ampWeighting )
        {
            //  This used to be an amplitude-weighted avg, but for many sounds, 
            //  particularly those for which the weighted avg would be very
            //  different from the simple avg, the amplitude-weighted avg
            //  emphasized the part of the sound in which the frequency estimates
            //  are least reliable (e.g. a piano tone). The unweighted 
            //  average should give more intuitive results in most cases.

            //	use sinusoidal amplitude:
            double a = bp.breakpoint().amplitude() * std::sqrt( 1. - bp.breakpoint().bandwidth() );                
            weight = pow( a, _ampWeighting );
        }
        
        weightedlabel += weight * computeFractionalChannelNumber( t, f );
	}
	
	int label = 0;
	if ( 0 < partial.numBreakpoints() ) //  should always be the case
	{        
		label = (int)((weightedlabel / partial.numBreakpoints()) + 0.5);
	}
	Assert( label >= 0 );
			
	//	assign label, and remember it, but
	//	only if it is a valid (positive) 
	//	distillation label:
	partial.setLabel( label );

}
// ---------------------------------------------------------------------------
//	channelize (one Partial)
// ---------------------------------------------------------------------------
//!	Label a Partial with the number of the frequency channel corresponding to
//!	the average frequency over all the Partial's Breakpoints.
//!	
//!	\param partial is the Partial to label.
//
void
Channelizer::channelize( Partial & partial ) const
{
	debugger << "channelizing Partial with " << partial.numBreakpoints() << " Breakpoints" << endl;
			
	//	compute an amplitude-weighted average channel
	//	label for each Partial:
	double ampsum = 0.;
	double weightedlabel = 0.;
	Partial::const_iterator bp;
	for ( bp = partial.begin(); bp != partial.end(); ++bp )
	{
		//	use sinusoidal amplitude:
		double a = bp.breakpoint().amplitude() * std::sqrt( 1. - bp.breakpoint().bandwidth() );
		
		//  This used to be an amplitude-weighted avg, but for many sounds, 
		//  particularly those for which the weighted avg would be very
		//  different from the simple avg, the amplitude-weighted avg
		//  emphasized the part of the sound in which the frequency estimates
		//  are least reliable (e.g. a piano tone). The unweighted 
		//  average should give more intuitive results in most cases.
				
		double f = bp.breakpoint().frequency();
		double t = bp.time();
		
		double refFreq = _refChannelFreq->valueAt( t ) / _refChannelLabel;
		// weightedlabel += a * (f / refFreq);
		weightedlabel += a * giveMeN( f, refFreq, _stretchFactor );
		ampsum += a;
	}
	
	int label;
	if ( ampsum > 0. )	
	// if ( 0 < partial.numBreakpoints() )
	{
		label = (int)((weightedlabel / ampsum) + 0.5);
	}
	else	//	this should never happen, but just in case:
	{
		label = 0;
	}
	Assert( label >= 0 );
			
	//	assign label, and remember it, but
	//	only if it is a valid (positive) 
	//	distillation label:
	partial.setLabel( label );

}
Exemple #17
0
Partial *PartialManager::allocPartial(int partNum) {
	Partial *outPartial = NULL;

	// Get the first inactive partial
	for (unsigned int partialNum = 0; partialNum < synth->getPartialCount(); partialNum++) {
		if (!partialTable[partialNum]->isActive()) {
			outPartial = partialTable[partialNum];
			break;
		}
	}
	if (outPartial != NULL) {
		outPartial->activate(partNum);
	}
	return outPartial;
}
Partial *PartialManager::allocPartial(int partNum) {
	Partial *outPartial = NULL;

	// Get the first inactive partial
	for (int partialNum = 0; partialNum < MT32EMU_MAX_PARTIALS; partialNum++) {
		if (!partialTable[partialNum]->isActive()) {
			outPartial = partialTable[partialNum];
			break;
		}
	}
	if (outPartial != NULL) {
		outPartial->activate(partNum);
	}
	return outPartial;
}
Exemple #19
0
void Poly::terminate() {
	if (state == POLY_Inactive) {
		return;
	}
	for (int t = 0; t < 4; t++) {
		Partial *partial = partials[t];
		if (partial != NULL) {
			partial->deactivate();
		}
	}
	if (state != POLY_Inactive) {
		// FIXME: Throw out lots of debug output - this should never happen
		// (Deactivating the partials above should've made them each call partialDeactivated(), ultimately changing the state to POLY_Inactive)
		state = POLY_Inactive;
	}
}
bool PartialBuilder::better_match( const Partial & part, const SpectralPeak & pk1,
                                   const SpectralPeak & pk2 )
{
	Assert( part.numBreakpoints() > 0 );
	
	return freq_distance( part, pk1 ) < freq_distance( part, pk2 );
}	                                   
Exemple #21
0
// ---------------------------------------------------------------------------
//	avgFrequency
// ---------------------------------------------------------------------------
//! Return the average frequency over all Breakpoints in this Partial.
//! Return zero if the Partial has no Breakpoints.
//!  
//! \param  p is the Partial to evaluate
//! \return the average frequency (Hz) of Breakpoints in the Partial p
//
double avgFrequency( const Partial & p )
{
    double avg = 0;
    for ( Partial::const_iterator it = p.begin();
          it != p.end();
          ++it )
    {
        avg += it->frequency();
    }
    
    if ( avg != 0 )
    {
        avg /= p.numBreakpoints();
    }
    
    return avg;
}
Exemple #22
0
Partial *PartialManager::allocPartial(int partNum) {
	Partial *outPartial = NULL;

	// Use the first inactive partial reserved for the specified part (if there are any)
	// Otherwise, use the last inactive partial, if any
	for (int i = 0; i < MT32EMU_MAX_PARTIALS; i++) {
		if (!partialTable[i]->isActive()) {
			outPartial = partialTable[i];
			if (partialReserveTable[i] == partNum)
				break;
		}
	}
	if (outPartial != NULL) {
		outPartial->activate(partNum);
		outPartial->age = 0;
	}
	return outPartial;
}
// ---------------------------------------------------------------------------
//	findContribution		(STATIC)
// ---------------------------------------------------------------------------
//	Find and return an iterator range delimiting the portion of pshort that
// 	should be spliced into the distilled Partial plong. If any Breakpoint 
//	falls in a zero-amplitude region of plong, then pshort should contribute,
//	AND its onset should be retained (!!! This is the weird part!!!). 
//  Therefore, if cbeg is not equal to cend, then cbeg is pshort.begin().
//
std::pair< Partial::iterator, Partial::iterator >
findContribution( Partial & pshort, const Partial & plong, 
				  double fadeTime, double gapTime )
{
	//	a Breakpoint can only fit in the gap if there's
	//	enough time to fade out pshort, introduce a
	//	space of length gapTime, and fade in the rest
	//	of plong (don't need to worry about the fade
	//	in, because we are checking that plong is zero
	//	at cbeg.time() + clearance anyway, so the fade 
	//	in must occur after that, and already be part of 
	//	plong):
    //
    //  WRONG if cbeg is before the start of plong.
    //  Changed so that all Partials are faded in and
    //  out before distilling, so now the clearance 
    //  need only be the gap time:
	double clearance = gapTime; // fadeTime + gapTime;
	
	Partial::iterator cbeg = pshort.begin();
	while ( cbeg != pshort.end() && 
			( plong.amplitudeAt( cbeg.time() ) > 0 ||
			  plong.amplitudeAt( cbeg.time() + clearance ) > 0 ) )
	{
		++cbeg;
	}
	
	Partial::iterator cend = cbeg;
	
	// if a gap is found, find the end of the
	// range of Breakpoints that fit in that
	// gap:
	while ( cend != pshort.end() &&
			plong.amplitudeAt( cend.time() ) == 0 &&
			plong.amplitudeAt( cend.time() + clearance ) == 0 )
	{
		++cend;
	}

	// if a gap is found, and it is big enough for at
	// least one Breakpoint, then include the 
	// onset of the Partial:
	if ( cbeg != pshort.end()  )
	{
		cbeg = pshort.begin();
	}
	
	return std::make_pair( cbeg, cend );
}
Exemple #24
0
// ---------------------------------------------------------------------------
//  fixPhaseBetween
//
//!	Fix the phase travel between two times by adjusting the
//!	frequency and phase of Breakpoints between those two times.
//!
//!	This algorithm assumes that there is nothing interesting about the
//!	phases of the intervening Breakpoints, and modifies their frequencies 
//!	as little as possible to achieve the correct amount of phase travel 
//!	such that the frequencies and phases at the specified times
//!	match the stored values. The phases of all the Breakpoints between 
//! the specified times are recomputed.
//!
//! THIS DOES NOT YET TREAT NULL BREAKPOINTS DIFFERENTLY FROM OTHERS.
//!
//! \pre        There must be at least one Breakpoint in the
//!             Partial between the specified times tbeg and tend.
//! \post       The phases and frequencies of the Breakpoints in the 
//!             range have been recomputed such that an oscillator
//!             initialized to the parameters of the first Breakpoint
//!             will arrive at the parameters of the last Breakpoint,
//!             and all the intervening Breakpoints will be matched.
//!	\param p    The partial whose phases and frequencies will be recomputed. 
//!             The Breakpoint at this position is unaltered.
//! \param tbeg The phases and frequencies of Breakpoints later than the 
//!             one nearest this time will be modified.
//! \param tend The phases and frequencies of Breakpoints earlier than the 
//!             one nearest this time will be modified. Should be greater 
//!             than tbeg, or else they will be swapped.
//
void fixPhaseBetween( Partial & p, double tbeg, double tend )
{
    if ( tbeg > tend )
    {
        std::swap( tbeg, tend );
    }

    // for Partials that do not extend over the entire
    // specified time range, just recompute phases from
    // beginning or end of the range:
    if ( p.endTime() < tend )
    {
        // OK if start time is also after tbeg, will
        // just recompute phases from start of p.
        fixPhaseAfter( p, tbeg );
    }
    else if ( p.startTime() > tbeg )
    {
        fixPhaseBefore( p, tend );
    }
    else
    {
        // invariant:
        // p begins before tbeg and ends after tend.
        Partial::iterator b = p.findNearest( tbeg );
        Partial::iterator e = p.findNearest( tend );

        // if there is a null Breakpoint n between b and e, then
        // should fix forward from b to n, and backward from
        // e to n. Otherwise, do this complicated thing.
        Partial::iterator nullbp = std::find_if( b, e, BreakpointUtils::isNull );
        if ( nullbp != e )
        {
            fixPhaseForward( b, nullbp );
            fixPhaseBackward( nullbp, e );
        }
        else
        {
            fixPhaseBetween( b, e );
        }
    }
}
// ---------------------------------------------------------------------------
//	absorb
// ---------------------------------------------------------------------------
//!	Absorb another Partial's energy as noise (bandwidth), 
//!	by accumulating the other's energy as noise energy
//!	in the portion of this Partial's envelope that overlaps
//!	(in time) with the other Partial's envelope.
//
void 
Partial::absorb( const Partial & other )
{
	Partial::iterator it = findAfter( other.startTime() );
	while ( it != end() && !(it.time() > other.endTime()) )
	{
		//	only non-null (non-zero-amplitude) Breakpoints
		//	abosrb noise energy because null Breakpoints
		//	are used especially to reset the Partial phase,
		//	and are not part of the normal analyasis data:
		if ( it->amplitude() > 0 )
		{
			// absorb energy from other at the time
			// of this Breakpoint:
			double a = other.amplitudeAt( it.time() );
			it->addNoiseEnergy( a * a );
		}	
		++it;
	}
}
// ---------------------------------------------------------------------------
//	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;
        */
    }
}
// ---------------------------------------------------------------------------
//	timeOfPeakEnergy (static helper function)
// ---------------------------------------------------------------------------
//	Return the time at which the given Partial attains its
//	maximum sinusoidal energy.
//
static double timeOfPeakEnergy( const Partial & p )
{
	Partial::const_iterator partialIter = p.begin();
	double maxAmp = 
		partialIter->amplitude() * std::sqrt( 1. - partialIter->bandwidth() );
	double time = partialIter.time();
	
	for ( ++partialIter; partialIter != p.end(); ++partialIter ) 
	{
		double a = partialIter->amplitude() * 
					std::sqrt( 1. - partialIter->bandwidth() );
		if ( a > maxAmp ) 
		{
			maxAmp = a;
			time = partialIter.time();
		}
	}			
	
	return time;
}
Exemple #28
0
// ---------------------------------------------------------------------------
//	NoiseRatioScaler function call operator
// ---------------------------------------------------------------------------
//	Scale the relative noise content of the specified Partial according 
//	to an envelope representing a (time-varying) noise energy 
//	scale value.
//
void 
NoiseRatioScaler::operator()( Partial & p ) const
{
	for ( Partial::iterator pos = p.begin(); pos != p.end(); ++pos ) 
	{		
		//	compute new bandwidth value:
		double bw = pos.breakpoint().bandwidth();
		if ( bw < 1. ) 
		{
			double ratio = bw  / (1. - bw);
			ratio *= env->valueAt( pos.time() );
			bw = ratio / ( 1. + ratio );
		}
		else 
		{
			bw = 1.;
		}		
		pos.breakpoint().setBandwidth( bw );
	}	
}
Exemple #29
0
std::vector<typename Partial::SolutionT> generate(Partial const & part, Constraint constr)
{
    using SolutionVec = std::vector<typename Partial::SolutionT>;

    if (part.isFinished(constr))
    {
        SolutionVec result{ part.getSolution() };
        return result;
    }
    else
    {
        Stream<Partial> partList = part.refine(constr);

        SolutionVec result;
        forEach(std::move(partList), [&](Partial const & part){
            SolutionVec lst = generate(part, constr);
            std::copy(lst.begin(), lst.end(), std::back_inserter(result));
        });
        return result;
    }
}
Exemple #30
0
// ---------------------------------------------------------------------------
//	weightedAvgFrequency
// ---------------------------------------------------------------------------
//! Return the average frequency over all Breakpoints in this Partial, 
//! weighted by the Breakpoint amplitudes.
//! Return zero if the Partial has no Breakpoints.
//!  
//! \param  p is the Partial to evaluate
//! \return the average frequency (Hz) of Breakpoints in the Partial p
//
double weightedAvgFrequency( const Partial & p )
{
    double avg = 0;
    double ampsum = 0;
    for ( Partial::const_iterator it = p.begin();
          it != p.end();
          ++it )
    {
        avg += it->amplitude() * it->frequency();
        ampsum += it->amplitude();
    }
    
    if ( avg != 0 && ampsum != 0 )
    {
        avg /= ampsum;
    }
    else
    {
        avg = 0;
    }
    
    return avg;
}