summaryrefslogtreecommitdiff
path: root/src/loris/SpectralSurface.h
diff options
context:
space:
mode:
authorJohn Glover <glover.john@gmail.com>2011-07-08 18:06:21 +0100
committerJohn Glover <glover.john@gmail.com>2011-07-08 18:06:21 +0100
commitd6073e01c933c77f1e2bc3c3fe1126d617003549 (patch)
tree695d23677c5b84bf3a0f88fbd4959b4f7cbc0e90 /src/loris/SpectralSurface.h
parent641688b252da468eb374674a0dbaae1bbac70b2b (diff)
downloadsimpl-d6073e01c933c77f1e2bc3c3fe1126d617003549.tar.gz
simpl-d6073e01c933c77f1e2bc3c3fe1126d617003549.tar.bz2
simpl-d6073e01c933c77f1e2bc3c3fe1126d617003549.zip
Start adding Loris files
Diffstat (limited to 'src/loris/SpectralSurface.h')
-rw-r--r--src/loris/SpectralSurface.h370
1 files changed, 370 insertions, 0 deletions
diff --git a/src/loris/SpectralSurface.h b/src/loris/SpectralSurface.h
new file mode 100644
index 0000000..3291f3d
--- /dev/null
+++ b/src/loris/SpectralSurface.h
@@ -0,0 +1,370 @@
+#ifndef INCLUDE_SPECTRALSURFACE_H
+#define INCLUDE_SPECTRALSURFACE_H
+/*
+ * 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
+ *
+ *
+ * SpectralSurface.h
+ *
+ * Definition of class SpectralSurface, a class representing
+ * a smoothed time-frequency surface that can be used to
+ * perform cross-synthesis, the filtering of one sound by the
+ * time-varying spectrum of another.
+ *
+ * Kelly Fitz, 21 Dec 2005
+ * loris@cerlsoundgroup.org
+ *
+ * http://www.cerlsoundgroup.org/Loris/
+ *
+ */
+
+#include "LorisExceptions.h"
+#include "Partial.h"
+#include "PartialList.h"
+#include "PartialUtils.h" // for compareLabelLess
+
+#include <algorithm> // for sort
+#include <vector>
+
+// begin namespace
+namespace Loris {
+
+// ---------------------------------------------------------------------------
+// Class SpectralSurface
+//
+//! SpectralSurface represents a smoothed time-frequency surface that
+//! can be used to perform cross-synthesis, the filtering of one sound
+//! by the time-varying spectrum of another.
+//
+class SpectralSurface
+{
+// -- public interface --
+public:
+
+// -- lifecycle --
+
+ //! Contsruct a new SpectralSurface from a sequence of distilled
+ //! Partials.
+ //!
+ //! \pre the specified Partials must be channelized and distilled.
+ //! \param b the beginning of the sequence of Partials
+ //! \param e the end of the sequence of Partials
+ //!
+ //! If compiled with NO_TEMPLATE_MEMBERS defined, then b and e
+ //! must be PartialList::iterators, otherwise they can be any type
+ //! of iterators over a sequence of Partials.
+#if ! defined(NO_TEMPLATE_MEMBERS)
+ template<typename Iter>
+ SpectralSurface( Iter b, Iter e );
+#else
+ inline
+ SpectralSurface( PartialList::iterator b, PartialList::iterator e );
+#endif
+
+ // use compiler-generated copy/assign/destroy
+
+// --- operations ---
+
+ //! Scale the amplitude of every Breakpoint in a Partial
+ //! according to the amplitude of the spectral surface
+ //! at the corresponding time and frequency.
+ //!
+ //! \param p the Partial to modify
+ void scaleAmplitudes( Partial & p );
+
+ //! Scale the amplitudes of a sequence of Partials
+ //! according to the amplitude of the spectral surface
+ //! at the corresponding times and frequencies,
+ //! performing cross-synthesis, the filtering of one
+ //! sound (the sequence of Partials) by the time-varying
+ //! spectrum of another sound (the Partials used to
+ //! construct the surface). The surface is stretched
+ //! in time and frequency according to the values of
+ //! the two stretch factors (default 1, no stretching)
+ //! and the amount of the effect is governed by the
+ //! `effect' parameter (default 1, full effect).
+ //!
+ //! \param b the beginning of the sequence of Partials
+ //! \param e the end of the sequence of Partials
+ //!
+ //! If compiled with NO_TEMPLATE_MEMBERS defined, then b and e
+ //! must be PartialList::iterators, otherwise they can be any type
+ //! of iterators over a sequence of Partials.
+#if ! defined(NO_TEMPLATE_MEMBERS)
+ template<typename Iter>
+ void scaleAmplitudes( Iter b, Iter e );
+#else
+ inline
+ void scaleAmplitudes( PartialList::iterator b, PartialList::iterator e );
+#endif
+
+ //! Set the amplitude of every Breakpoint in a Partial
+ //! equal to the amplitude of the spectral surface
+ //! at the corresponding time and frequency.
+ //!
+ //! \param p the Partial to modify
+ void setAmplitudes( Partial & p );
+
+ //! Set the amplitudes of a sequence of Partials
+ //! equal to the amplitude of the spectral surface
+ //! at the corresponding times and frequencies.
+ //! This can be used to perform formant-corrected
+ //! pitch shifting of a sound: construct the surface
+ //! from the unmodified Partials, perform the pitch
+ //! shift on the Partials, then apply the surface
+ //! to the shifted Partials using setAmplitudes.
+ //! The surface is stretched
+ //! in time and frequency according to the values of
+ //! the two stretch factors (default 1, no stretching)
+ //! and the amount of the effect is governed by the
+ //! `effect' parameter (default 1, full effect).
+ //!
+ //! \param b the beginning of the sequence of Partials
+ //! \param e the end of the sequence of Partials
+ //!
+ //! If compiled with NO_TEMPLATE_MEMBERS defined, then b and e
+ //! must be PartialList::iterators, otherwise they can be any type
+ //! of iterators over a sequence of Partials.
+#if ! defined(NO_TEMPLATE_MEMBERS)
+ template<typename Iter>
+ void setAmplitudes( Iter b, Iter e );
+#else
+ inline
+ void setAmplitudes( PartialList::iterator b, PartialList::iterator e );
+#endif
+
+// --- access/mutation ---
+
+ //! Return the amount of strecthing in the frequency dimension
+ //! (default 1, no stretching). Values greater than 1 stretch
+ //! the surface in the frequency dimension, values less than 1
+ //! (but greater than 0) compress the surface in the frequency
+ //! dimension.
+ double frequencyStretch( void ) const;
+
+ //! Return the amount of strecthing in the time dimension
+ //! (default 1, no stretching). Values greater than 1 stretch
+ //! the surface in the time dimension, values less than 1
+ //! (but greater than 0) compress the surface in the time
+ //! dimension.
+ double timeStretch( void ) const;
+
+ //! Return the amount of effect applied by scaleAmplitudes
+ //! and setAmplitudes (default 1, full effect). Values
+ //! less than 1 (but greater than 0) reduce the amount of
+ //! amplitude modified performed by application of the
+ //! surface. (This is rarely a good way of controlling the
+ //! amount of the effect.)
+ double effect( void ) const;
+
+ //! Set the amount of strecthing in the frequency dimension
+ //! (default 1, no stretching). Values greater than 1 stretch
+ //! the surface in the frequency dimension, values less than 1
+ //! (but greater than 0) compress the surface in the frequency
+ //! dimension.
+ //!
+ //! \pre stretch must be positive
+ //! \param stretch the new stretch factor for the frequency dimension
+ void setFrequencyStretch( double stretch );
+
+ //! Set the amount of strecthing in the time dimension
+ //! (default 1, no stretching). Values greater than 1 stretch
+ //! the surface in the time dimension, values less than 1
+ //! (but greater than 0) compress the surface in the time
+ //! dimension.
+ //!
+ //! \pre stretch must be positive
+ //! \param stretch the new stretch factor for the time dimension
+ void setTimeStretch( double stretch );
+
+ //! Set the amount of effect applied by scaleAmplitudes
+ //! and setAmplitudes (default 1, full effect). Values
+ //! less than 1 (but greater than 0) reduce the amount of
+ //! amplitude modified performed by application of the
+ //! surface. (This is rarely a good way of controlling the
+ //! amount of the effect.)
+ //!
+ //! \pre effect must be between 0 and 1, inclusive
+ //! \param effect the new factor controlling the amount of
+ //! amplitude modification performed by scaleAmplitudes
+ //! and setAmplitudes
+ void setEffect( double effect );
+
+private:
+
+// -- instance variables --
+
+ std::vector< Partial > mPartials; //! the Partials comprising the surface are
+ //! stored in a vector for easy random access
+ double mStretchFreq; //! stretch factor for the frequency dimension
+ double mStretchTime; //! stretch factor for the time dimension
+ double mEffect; //! factor for controlling the amount of
+ //! of the effect applied in setAmplitudes and
+ //! scaleAmplitudes: 0 gives unmodified amplitudes
+ //! 1 gives fully modified amplitudes.
+ double mMaxSurfaceAmp; //! the maximum amplitude of any Breakpoint on
+ //! the surface, used for normalizing the surface
+ //! amplitude for scaleAmplitudes
+
+// --- private helpers ---
+
+ // helper used by constructor for adding Partials one by one
+ void addPartialAux( const Partial & p );
+
+};
+
+// ---------------------------------------------------------------------------
+// constructor
+// ---------------------------------------------------------------------------
+//! Contsruct a new SpectralSurface from a sequence of distilled
+//! Partials.
+//!
+//! \pre the specified Partials must be channelized and distilled.
+//! \param b the beginning of the sequence of Partials
+//! \param e the end of the sequence of Partials
+//!
+//! If compiled with NO_TEMPLATE_MEMBERS defined, then b and e
+//! must be PartialList::iterators, otherwise they can be any type
+//! of iterators over a sequence of Partials.
+//
+#if ! defined(NO_TEMPLATE_MEMBERS)
+template<typename Iter>
+SpectralSurface::SpectralSurface( Iter b, Iter e ) :
+#else
+inline
+SpectralSurface::SpectralSurface( PartialList::iterator b,
+ PartialList::iterator e ) :
+#endif
+ mStretchFreq( 1.0 ),
+ mStretchTime( 1.0 ),
+ mEffect( 1.0 ),
+ mMaxSurfaceAmp( 0.0 )
+{
+ // add only labeled Partials:
+ while ( b != e )
+ {
+ if ( b->label() != 0 )
+ {
+ addPartialAux( *b );
+ }
+ ++b;
+ }
+
+ // complain if the Partials were not distilled
+ if ( mPartials.empty() )
+ {
+ Throw( InvalidArgument, "Partals need to be distilled to build a SpectralSurface" );
+ }
+
+ if ( 0 == mMaxSurfaceAmp )
+ {
+ Throw( InvalidArgument, "The SpectralSurface is zero amplitude everywhere!" );
+ }
+
+ // sort by label
+ std::sort( mPartials.begin(), mPartials.end(), PartialUtils::compareLabelLess() );
+}
+
+
+// ---------------------------------------------------------------------------
+// scaleAmplitudes
+// ---------------------------------------------------------------------------
+//! Scale the amplitudes of a sequence of Partials
+//! according to the amplitude of the spectral surface
+//! at the corresponding times and frequencies,
+//! performing cross-synthesis, the filtering of one
+//! sound (the sequence of Partials) by the time-varying
+//! spectrum of another sound (the Partials used to
+//! construct the surface). The surface is stretched
+//! in time and frequency according to the values of
+//! the two stretch factors (default 1, no stretching)
+//! and the amount of the effect is governed by the
+//! `effect' parameter (default 1, full effect).
+//!
+//! \param b the beginning of the sequence of Partials
+//! \param e the end of the sequence of Partials
+//!
+//! If compiled with NO_TEMPLATE_MEMBERS defined, then b and e
+//! must be PartialList::iterators, otherwise they can be any type
+//! of iterators over a sequence of Partials.
+//
+#if ! defined(NO_TEMPLATE_MEMBERS)
+template<typename Iter>
+void SpectralSurface::scaleAmplitudes( Iter b, Iter e )
+#else
+inline
+void SpectralSurface::scaleAmplitudes( PartialList::iterator b,
+ PartialList::iterator e )
+#endif
+{
+ while ( b != e )
+ {
+ // debugger << b->label() << endl;
+ scaleAmplitudes( *b );
+ ++b;
+ }
+}
+
+// ---------------------------------------------------------------------------
+// setAmplitudes
+// ---------------------------------------------------------------------------
+//! Set the amplitudes of a sequence of Partials
+//! equal to the amplitude of the spectral surface
+//! at the corresponding times and frequencies.
+//! This can be used to perform formant-corrected
+//! pitch shifting of a sound: construct the surface
+//! from the unmodified Partials, perform the pitch
+//! shift on the Partials, then apply the surface
+//! to the shifted Partials using setAmplitudes.
+//! The surface is stretched
+//! in time and frequency according to the values of
+//! the two stretch factors (default 1, no stretching)
+//! and the amount of the effect is governed by the
+//! `effect' parameter (default 1, full effect).
+//!
+//! \param b the beginning of the sequence of Partials
+//! \param e the end of the sequence of Partials
+//!
+//! If compiled with NO_TEMPLATE_MEMBERS defined, then b and e
+//! must be PartialList::iterators, otherwise they can be any type
+//! of iterators over a sequence of Partials.
+//
+#if ! defined(NO_TEMPLATE_MEMBERS)
+template<typename Iter>
+void SpectralSurface::setAmplitudes( Iter b, Iter e )
+#else
+inline
+void SpectralSurface::setAmplitudes( PartialList::iterator b,
+ PartialList::iterator e )
+#endif
+{
+ while ( b != e )
+ {
+ // debugger << b->label() << endl;
+ setAmplitudes( *b );
+ ++b;
+ }
+}
+
+} // namespace Loris
+
+#endif /* ndef INCLUDE_SPECTRALSURFACE_H */
+