lib/minim/src/ddf/minim/ugens/Wavetable.java
/**
	 * Warping works by choosing a point in the waveform, the warpPoint, and
	 * then specifying where it should move to, the warpTarget. Both values
	 * should be normalized (i.e. in the range [0,1]). What will happen is that
	 * the waveform data in front of and behind the warpPoint will be squashed
	 * or stretch to fill the space defined by where the warpTarget is. For
	 * instance, if you took Waves.SQUARE and called warp( 0.5, 0.2 ), you would
	 * wind up with a square wave with a 20 percent duty cycle, the same as
	 * using Waves.square( 0.2 ). This is because the crossover point of a
	 * square wave is halfway through and warping it such that the crossover is
	 * moved to 20% through the waveform is equivalent to changing the duty
	 * cycle. Or course, much more interesting things happen when warping a more
	 * complex waveform, such as one returned by the Waves.randomNHarms method,
	 * especially if it is warped more than once.
	 * 
	 * @shortdesc Warping works by choosing a point in the waveform, the
	 *            warpPoint, and then specifying where it should move to, the
	 *            warpTarget.
	 *            
	 * @example Synthesis/WavetableMethods
	 * 
	 * @param warpPoint
	 *            float: the point in the wave for to be moved, expressed as a
	 *            normalized value.
	 * @param warpTarget
	 *            float: the point in the wave to move the warpPoint to,
	 *            expressed as a normalized value.
	 *            
	 * @related Wavetable
	 */
Warping works by choosing a point in the waveform, the warpPoint, and
then specifying where it should move to, the warpTarget. Both values
should be normalized . What will happen is that
the waveform data in front of and behind the warpPoint will be squashed
or stretch to fill the space defined by where the warpTarget is. For
instance, if you took Waves.SQUARE and called warp( 0.5, 0.2 ), you would
wind up with a square wave with a 20 percent duty cycle, the same as
using Waves.square( 0.2 ). This is because the crossover point of a
square wave is halfway through and warping it such that the crossover is
moved to 20% through the waveform is equivalent to changing the duty
cycle. Or course, much more interesting things happen when warping a more
complex waveform, such as one returned by the Waves.randomNHarms method,
especially if it is warped more than once.

@shortdesc Warping works by choosing a point in the waveform, the
warpPoint, and then specifying where it should move to, the
warpTarget.



@param warpPoint
float: the point in the wave for to be moved, expressed as a
normalized value.
@param warpTarget
float: the point in the wave to move the warpPoint to,
expressed as a normalized value.

@related Wavetable
Warping works by choosing a point in the waveform the warpPoint and then specifying where it should move to the warpTarget . Both values should be normalized . What will happen is that the waveform data in front of and behind the warpPoint will be squashed or stretch to fill the space defined by where the warpTarget is . For instance if you took Waves . SQUARE and called warp ( 0 . 5 0 . 2 ) you would wind up with a square wave with a 20 percent duty cycle the same as using Waves . square ( 0 . 2 ) . This is because the crossover point of a square wave is halfway through and warping it such that the crossover is moved to 20% through the waveform is equivalent to changing the duty cycle . Or course much more interesting things happen when warping a more complex waveform such as one returned by the Waves . randomNHarms method especially if it is warped more than once . @shortdesc Warping works by choosing a point in the waveform the warpPoint and then specifying where it should move to the warpTarget . @param warpPoint float : the point in the wave for to be moved expressed as a normalized value . @param warpTarget float : the point in the wave to move the warpPoint to expressed as a normalized value . @related Wavetable
public void warp(float warpPoint, float warpTarget)
	{
		float[] newWave = new float[waveform.length];
		for ( int s = 0; s < newWave.length; ++s )
		{
			float lookup = (float)s / newWave.length;
			if ( lookup <= warpTarget )
			{
				lookup = ( lookup / warpTarget ) * warpPoint;
			}
			else
			{
				lookup = warpPoint + ( 1 - ( 1 - lookup ) / ( 1 - warpTarget ) ) * ( 1 - warpPoint );
			}
			newWave[s] = value( lookup );
		}
		waveform = newWave;
	}
public void warp ( float warpPoint , float warpTarget ) { float [ ] newWave = new float [ waveform . length ] ; for ( int s = 0 ; s < newWave . length ; ++ s ) { float lookup = ( float ) s / newWave . length ; if ( lookup <= warpTarget ) { lookup = ( lookup / warpTarget ) * warpPoint ; } else { lookup = warpPoint + ( 1 - ( 1 - lookup ) / ( 1 - warpTarget ) ) * ( 1 - warpPoint ) ; } newWave [ s ] = value ( lookup ) ; } waveform = newWave ; }
Warping works by choosing a point in the waveform, the warpPoint, and
 then specifying where it should move to, the warpTarget.
Warping works by choosing a point in the waveform the warpPoint and then specifying where it should move to the warpTarget .
// normalize look up to [0,warpTarget], expand to [0,warpPoint] // map (warpTarget,1] to (warpPoint,1]