diff options
Diffstat (limited to 'src/loris/Harmonifier.C')
| -rw-r--r-- | src/loris/Harmonifier.C | 158 | 
1 files changed, 158 insertions, 0 deletions
| diff --git a/src/loris/Harmonifier.C b/src/loris/Harmonifier.C new file mode 100644 index 0000000..3a41c58 --- /dev/null +++ b/src/loris/Harmonifier.C @@ -0,0 +1,158 @@ +/* + * This is the Loris C++ Class Library, implementing analysis,  + * manipulation, and synthesis of digitized sounds using the Reassigned  + * Bandwidth-Enhanced Additive Sound Model. + * + * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY, without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + * + * + * Harmonifier.h + * + * Definition of class Harmonifier. + * + * Kelly Fitz, 26 Oct 2005 + * loris@cerlsoundgroup.org + * + * http://www.cerlsoundgroup.org/Loris/ + * + */ +#include "Harmonifier.h" + +#include "LinearEnvelope.h" + +#include <cmath>    // for pow + +using namespace Loris;  + + +// --------------------------------------------------------------------------- +//    Constructor +// --------------------------------------------------------------------------- +//! Construct a new Harmonifier that applies the specified  +//! reference Partial to fix the frequencies of Breakpoints +//! whose amplitude is below threshold_dB (0 by default, +//! to apply only to quiet Partials, specify a threshold, +//! like -90).  +// +Harmonifier::Harmonifier( const Partial & ref, double threshold_dB ) : +    _refPartial( ref ), +    _freqFixThresholdDb( threshold_dB ), +    _weight( createDefaultEnvelope() ) +{ +    if ( 0 == _refPartial.numBreakpoints() ) +    { +        Throw( InvalidArgument,  +               "Cannot use an empty reference Partial in Harmonizer" ); +    } +    if ( 0 == _refPartial.label() ) +    { +        //  if the reference is unlabeled, assume that it is the fundamental +        _refPartial.setLabel( 1 ); +    } +     +} + +// --------------------------------------------------------------------------- +//    Constructor +// --------------------------------------------------------------------------- +//! Construct a new Harmonifier that applies the specified  +//! reference Partial to fix the frequencies of Breakpoints +//! whose amplitude is below threshold_dB (0 by default, +//! to apply only to quiet Partials, specify a threshold, +//! like -90). The Envelope is a time-varying weighting  +//! on the harmonifing process. When 1, harmonic frequencies +//! are used, when 0, breakpoint frequencies are unmodified.  +// +Harmonifier::Harmonifier( const Partial & ref, const Envelope & env,  +                          double threshold_dB ) : +    _refPartial( ref ), +    _freqFixThresholdDb( threshold_dB ), +    _weight( env.clone() ) +{ +    if ( 0 == _refPartial.numBreakpoints() ) +    { +        Throw( InvalidArgument,  +               "Cannot use an empty reference Partial in Harmonizer" ); +    } +    if ( 0 == _refPartial.label() ) +    { +        //  if the reference is unlabeled, assume that it is the fundamental +        _refPartial.setLabel( 1 ); +    } +     +} + +// --------------------------------------------------------------------------- +//    Destructor +// --------------------------------------------------------------------------- +Harmonifier::~Harmonifier( void ) +{ +} + +// --------------------------------------------------------------------------- +//    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() ) ); +        } + +    } +} + +// --------------------------------------------------------------------------- +//    createDefaultEnvelope (STATIC) +// --------------------------------------------------------------------------- +//! Return the default weighing envelope (always 1). +//! Used in template constructors. +// +Envelope * Harmonifier::createDefaultEnvelope( void ) +{ +    return new LinearEnvelope( 1 ); +}     + |