From d6073e01c933c77f1e2bc3c3fe1126d617003549 Mon Sep 17 00:00:00 2001
From: John Glover <glover.john@gmail.com>
Date: Fri, 8 Jul 2011 18:06:21 +0100
Subject: Start adding Loris files

---
 src/loris/Harmonifier.C | 158 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 158 insertions(+)
 create mode 100644 src/loris/Harmonifier.C

(limited to 'src/loris/Harmonifier.C')

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 );
+}    
+
-- 
cgit v1.2.3