diff options
Diffstat (limited to 'src/loris/phasefix.h')
-rw-r--r-- | src/loris/phasefix.h | 237 |
1 files changed, 237 insertions, 0 deletions
diff --git a/src/loris/phasefix.h b/src/loris/phasefix.h new file mode 100644 index 0000000..016983d --- /dev/null +++ b/src/loris/phasefix.h @@ -0,0 +1,237 @@ +#ifndef PHASEFIX_H +#define PHASEFIX_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 + * + * + * phasefix.h + * + * Functions for correcting Breakpoint phases and frequencies so that + * stored phases match the phases that would be synthesized using the + * Loris Synthesizer. + * + * Kelly Fitz, 23 Sept 04 + * loris@cerlsoundgroup.org + * + * http://www.cerlsoundgroup.org/Loris/ + * + */ +#include "Partial.h" + +// begin namespace +namespace Loris { + +// FUNCTION PROTOYPES + +// fixPhaseBackward +// +//! Recompute phases of all Breakpoints on the half-open range [stopHere, pos) +//! so that the synthesized phases of those Breakpoints matches +//! the stored phase, as long as the synthesized phase at stopHere +//! matches the stored (not recomputed) phase. +//! +//! The phase is corrected beginning at the end of the range, maintaining +//! the stored phase in the Breakpoint at pos. +//! +//! 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 range +//! (the front part) is fixed in the forward direction, beginning at +//! the start of the stopHere. +//! +//! \pre pos and stopHere are iterators on the same Partial, and +//! pos must be not later than stopHere. +//! \pre pos cannot be end of the Partial, it must be the postion +//! of a valid Breakpoint. +//! \param stopHere the position of the earliest Breakpoint whose phase might be +//! recomputed. +//! \param pos the position of a (later) Breakpoint whose phase is to be matched. +//! The phase at pos is not modified. +// +void fixPhaseBackward( Partial::iterator stopHere, Partial::iterator pos ); + +// fixPhaseForward +// +//! Recompute phases of all Breakpoints on the closed range [pos, stopHere] +//! so that the synthesized phases of those Breakpoints matches +//! the stored phase, as long as the synthesized phase at pos +//! matches the stored (not recomputed) phase. The phase at pos +//! is modified only if pos is the position of a null Breakpoint +//! and the Breakpoint that follows is non-null. +//! +//! 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 corrected from its non-Null +//! successor, if it has one, otherwise it is unmodified. +//! +//! \pre pos and stopHere are iterators on the same Partial, and +//! pos must be not later than stopHere. +//! \pre stopHere cannot be end of the Partial, it must be the postion +//! of a valid Breakpoint. +//! \param pos the position of the first Breakpoint whose phase might be +//! recomputed. +//! \param stopHere the position of the last Breakpoint whose phase might +//! be modified. +// +void fixPhaseForward( Partial::iterator pos, Partial::iterator stopHere ); + +// --------------------------------------------------------------------------- +// fixPhaseBetween +// +//! Fix the phase travel between two Breakpoints by adjusting the +//! frequency and phase of Breakpoints between those two. +//! +//! 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. +//! +//! Null Breakpoints are treated the same as non-null Breakpoints. +//! +//! \pre b and e are iterators on the same Partials, and +//! e must not preceed b in that Partial. +//! \pre There must be at least one Breakpoint in the +//! Partial between b and e. +//! \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 b The phases and frequencies of Breakpoints later than +//! this one may be modified. +//! \param e The phases and frequencies of Breakpoints earlier than +//! this one may be modified. +// +void fixPhaseBetween( Partial::iterator b, Partial::iterator e ); + +// 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. +//! +//! \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 = 0.2 ); + +// fixFrequency +// +//! Adjust frequencies of the Breakpoints in the +//! specified Partials such that the rendered Partial +//! achieves (or matches as nearly as possible, within +//! the constraint of the maximum allowable frequency +//! alteration) the analyzed phases. +//! +//! \param b The beginning of a range of Partials whose +//! frequencies should be fixed. +//! \param e The end of a range of Partials whose frequencies +//! should be fixed. +//! \param maxFixPct The maximum allowable frequency +//! alteration, default is 0.2%. +// +template < class Iter > +void fixFrequency( Iter b, Iter e, double maxFixPct = 0.2 ) +{ + while ( b != e ) + { + fixFrequency( *b, maxFixPct ); + ++b; + } +} + +// --------------------- useful phase maintenance utilities --------------------- + +// matchPhaseFwd +// +//! Compute the target frequency that will affect the +//! predicted (by the Breakpoint phases) amount of +//! sinusoidal phase travel between two breakpoints, +//! and assign that frequency to the target Breakpoint. +//! After computing the new frequency, update the phase of +//! the later Breakpoint. +//! +//! The most common kinds of errors are local (or burst) errors in +//! frequency and phase. These errors are best corrected by correcting +//! less than half the detected error at any time. Correcting more +//! than that will produce frequency oscillations for the remainder of +//! the Partial, in the case of a single bad frequency (as is common +//! at the onset of a tone). Any damping factor less then one will +//! converge eventually, .5 or less will converge without oscillating. +//! Use the damping argument to control the damping of the correction. +//! Specify 1 for no damping. +//! +//! +//! \pre The two Breakpoints are assumed to be consecutive in +//! a Partial. +//! \param bp0 The earlier Breakpoint. +//! \param bp1 The later Breakpoint. +//! \param dt The time (in seconds) between bp0 and bp1. +//! \param damping The fraction of the amount of phase error that will +//! be corrected (.5 or less will prevent frequency oscilation +//! due to burst errors in phase). +//! \param maxFixPct The maximum amount of frequency adjustment +//! that can be made to the frequency of bp1, expressed +//! as a precentage of the unmodified frequency of bp1. +//! If the necessary amount of frequency adjustment exceeds +//! this amount, then the phase will not be matched, +//! but will be updated as well to be consistent with +//! the frequencies. (default is 0.2%) +// +void matchPhaseFwd( Breakpoint & bp0, Breakpoint & bp1, + double dt, double damping, double maxFixPct = 0.2 ); + +// phaseTravel +// +//! Compute the sinusoidal phase travel between two Breakpoints. +//! Return the total unwrapped phase travel. +//! +//! \pre The two Breakpoints are assumed to be consecutive in +//! a Partial. +//! \param bp0 The earlier Breakpoint. +//! \param bp1 The later Breakpoint. +//! \param dt The time (in seconds) between bp0 and bp1. +//! \return The total unwrapped phase travel in radians. +// +double phaseTravel( const Breakpoint & bp0, const Breakpoint & bp1, double dt ); + +// wrapPi +// +//! Wrap an unwrapped phase value to the range (-pi,pi]. +//! +//! \param x The unwrapped phase in radians. +//! \return The phase (in radians) wrapped to the range (-Pi,Pi]. +// +double wrapPi( double x ); + + +} // end of namespace Loris + +#endif // ndef PHASEFIX_H + |