package ddf.minim.ugens; import ddf.minim.AudioOutput; import ddf.minim.Minim; import ddf.minim.UGen; /** * A UGen that generates a simple envelope that changes from a starting value to a * middle value during an "attack" phase and then changes to an ending value * during a "damp" or "decay" phase. By default, if you only specify a damp time, * it will change from 1 to 0 over that period of time. Specifying only attack and * damp time, it will ramp up from 0 to 1 over the attack time and then 1 to 0 over * the damp time. All times are specified in seconds. * * @example Synthesis/dampExample * * @author Anderson Mills * * @related UGen */ public class Damp extends UGen { /** * The default input is "audio." You don't need to patch directly to this input, * patching to the UGen itself will accomplish the same thing. * * @related Damp * @related UGen.UGenInput */ public UGenInput audio; // the maximum amplitude of the damp private float maxAmp; // the current amplitude private float amp; // the time from maxAmp to afterAmplitude private float dampTime; // the time from beforeAmplitude to maxAmp private float attackTime; // amplitude before the damp hits private float beforeAmplitude; // amplitude after the release of the damp private float afterAmplitude; // the current size of the step private float timeStepSize; // the current time private float now; // the damp has been activated private boolean isActivated; // unpatch the note after it's finished private boolean unpatchAfterDamp; // it might need to unpatch from an output private AudioOutput output; // or it might need to unpatch from another ugen private UGen ugenOutput; /** * Constructor for Damp envelope. * attackTime, rise time of the damp envelope, defaults to 0. * dampTime, decay time of the damp envelope, defaults to 1. * maxAmp, maximum amlitude of the damp envelope, defaults to 1. * befAmp, amplitude before the damp envelope, * and aftAmp, amplitude after the damp envelope, * default to 0. */ public Damp() { this( 0.0f, 1.0f, 1.0f, 0.0f, 0.0f ); } /** * Constructor for Damp envelope. * attackTime, rise time of the damp envelope, defaults to 0. * maxAmp, maximum amlitude of the damp envelope, defaults to 1. * befAmp, amplitude before the damp envelope, * and aftAmp, amplitude after the damp envelope, * default to 0. * @param dampTime * float: decay time of the damp envelope, in seconds */ public Damp( float dampTime ) { this( 0.0f, dampTime, 1.0f, 0.0f, 0.0f ); } /** * Constructor for Damp envelope. * maxAmp, maximum amlitude of the damp envelope, defaults to 1. * befAmp, amplitude before the damp envelope, * and aftAmp, amplitude after the damp envelope, * default to 0. * @param attackTime * float: rise time of the damp envelope, in seconds * @param dampTime * float: decay time of the damp envelope, in seconds */ public Damp( float attackTime, float dampTime ) { this( attackTime, dampTime, 1.0f, 0.0f, 0.0f ); } /** * Constructor for Damp envelope. * befAmp, amplitude before the damp envelope, * and aftAmp, amplitude after the damp envelope, * default to 0. * @param attackTime * float: rise time of the damp envelope, in seconds * @param dampTime * float: decay time of the damp envelope, in seconds * @param maxAmp * float: maximum amplitude of the damp envelope */ public Damp( float attackTime, float dampTime, float maxAmp ) { this( attackTime, dampTime, maxAmp, 0.0f, 0.0f ); } /** * Constructor for Damp envelope. * @param attackTime * float: rise time of the damp envelope, in seconds * @param dampTime * float: decay time of the damp envelope, in seconds * @param maxAmp * float: maximum amplitude of the damp envelope * @param befAmp * float: amplitude before the damp envelope * @param aftAmp * float: amplitude after the damp envelope */ public Damp( float attackTime, float dampTime, float maxAmp, float befAmp, float aftAmp ) { super(); audio = new UGenInput(InputType.AUDIO); this.attackTime = attackTime; this.dampTime = dampTime; this.maxAmp = maxAmp; beforeAmplitude = befAmp; afterAmplitude = aftAmp; isActivated = false; amp = beforeAmplitude; Minim.debug(" attackTime = " + attackTime + " dampTime = " + dampTime + " maxAmp = " + this.maxAmp + " now = " + now ); } /** * Specifies that the damp envelope should begin. * * @example Synthesis/dampExample * * @related Damp */ public void activate() { now = 0f; isActivated = true; if( timeStepSize > attackTime ) { amp = maxAmp; } else { amp = 0f; } } /** * Permits the setting of the attackTime parameter. * * @param attackTime * float: rise time of the damp envelope, in seconds * * @related Damp */ public void setAttackTime( float attackTime ) { this.attackTime = attackTime; } /** * Permits the setting of the attackTime parameter. * * @param dampTime * float: decay time of the damp envelope, in seconds * * @related Damp */ public void setDampTime( float dampTime ) { this.dampTime = dampTime; } /** * Set the attack time and damp time parameters based on a duration. * If the current attack time is positive, and less than the total duration, * then the damp time is the total duration after the attack time, otherwise, * the attack time and damp time are both set to half the duration. * * @shortdesc Set the attack time and damp time parameters based on a duration. * * @param duration * float: duration of the entire damp envelope, in seconds * * @related Damp * * @example Synthesis/dampExample */ public void setDampTimeFromDuration( float duration ) { float tmpDampTime = duration - attackTime; if ( tmpDampTime > 0.0f ) { dampTime = tmpDampTime; } else { attackTime = duration/2.0f; dampTime = duration/2.0f; } } @Override protected void sampleRateChanged() { timeStepSize = 1/sampleRate(); } /** * Tell this Damp that it should unpatch itself from the output after the release time. * * @param output * AudioOutput: the output this should unpatch from * * @example Synthesis/dampExample * * @related Damp */ public void unpatchAfterDamp( AudioOutput output ) { unpatchAfterDamp = true; this.output = output; } /** * The UGen this Damp should unpatch itself from after the release time. * * @param output * the UGen that this Damp should unpatch to after the Damp completes * * @related Damp */ public void unpatchAfterDamp( UGen output ) { unpatchAfterDamp = true; ugenOutput = output; } @Override protected void uGenerate( float[] channels ) { // before the damp if ( !isActivated ) { for( int i = 0; i < channels.length; i++ ) { channels[ i ] = beforeAmplitude*audio.getLastValues()[ i ]; } } // after the damp else if ( now >= ( dampTime + attackTime ) ) { for( int i = 0; i < channels.length; i++ ) { channels[ i ] = afterAmplitude*audio.getLastValues()[ i ]; } if ( unpatchAfterDamp ) { if ( output != null ) { unpatch( output ); output = null; } else if ( ugenOutput != null ) { unpatch( ugenOutput ); ugenOutput = null; } unpatchAfterDamp = false; Minim.debug(" unpatching Damp "); } } // after the attack, during the decay else if ( now >= attackTime ) // in the damp time { amp += ( afterAmplitude - amp )*timeStepSize/( dampTime + attackTime - now ); for( int i = 0; i < channels.length; i++ ) { channels[i] = amp*audio.getLastValues()[ i ]; } now += timeStepSize; } else // in the attack time { amp += ( maxAmp - amp )*timeStepSize/( attackTime - now ); for( int i = 0; i < channels.length; i++ ) { channels[i] = amp*audio.getLastValues()[ i ]; } now += timeStepSize; } } }