/*
* Modulator.java
* (FScape)
*
* Copyright (c) 2001-2016 Hanns Holger Rutz. All rights reserved.
*
* This software is published under the GNU General Public License v3+
*
*
* For further information, please contact Hanns Holger Rutz at
* contact@sciss.de
*/
package de.sciss.fscape.util;
import de.sciss.fscape.spect.*;
/**
* @version 0.71, 14-Nov-07
*/
public class Modulator
{
// -------- public variables --------
// -------- private variables --------
protected Curve curve[]; // atk/rls/sus in ABS_UNIT transformiert!
protected double atkStart = 0.0; // [ms]
protected double atkEnd = 0.0;
protected double susStart = 0.0;
protected double susPeriod = 0.0;
protected double rlsStart = 0.0;
protected double rlsEnd = 0.0;
protected double streamLength = 0.0;
protected double frameLength = 0.0;
protected Param base;
protected Param depth;
protected Envelope env;
protected SpectStream stream;
// -------- public methods --------
/**
* @param base in ABS_UNIT
* @param depth Ausmass (Envelope-Maximum) der Modulation von base
* @param env Verlauf der Modulation (-100% ... +100%), d.h.
* vSpace.unit sollte Param.FACTOR sein!
* @param refStream Referenz, die z.B. fuer BPM-Geschwindigkeit benoetigt wird
* ; hieran wird auch der Zeitoffset gemessen!
*/
public Modulator( Param base, Param depth, Envelope env, SpectStream refStream )
{
ParamSpace hSpace;
Param min, max;
Curve c = null;
Param hRef;
this.base = base;
this.depth = depth;
this.env = env;
this.stream = refStream;
// Stream Laenge
if( stream != null ) {
frameLength = SpectStream.framesToMillis( stream, 1 );
streamLength= SpectStream.framesToMillis( stream, stream.frames );
}
// Kurve in ABS_UNIT transformieren
curve = new Curve[ 3 ];
rlsStart = streamLength;
rlsEnd = streamLength;
// atk+rls benutzen streamLength als Referenz
hRef = new Param( streamLength, env.hUnit );
for( int i = 0; i < 3; i++ ) {
switch( i ) {
case 0:
c = env.atkState ? env.atkCurve : null;
break;
case 1:
c = env.rlsState ? env.rlsCurve : null;
break;
case 2:
c = env.susState ? env.susCurve : null;
hRef = new Param( rlsStart - atkEnd, env.hUnit ); // 100% sus = stream-atk-rls
break;
default:
break;
}
if( c == null) continue;
min = Param.transform( new Param( c.hSpace.min, c.hSpace.unit ), env.hUnit,
hRef, stream );
max = Param.transform( new Param( c.hSpace.max, c.hSpace.unit ), env.hUnit,
hRef, stream );
if( (min != null) && (max != null) ) {
hSpace = new ParamSpace( min.value, max.value, 0.0001, env.hUnit );
curve[ i ] = Curve.transform( c, hSpace, c.vSpace, hRef, null, stream );
switch( i ) {
case 0:
atkStart = hSpace.min;
atkEnd = hSpace.max;
break;
case 1:
rlsStart -= (hSpace.max - hSpace.min);
break;
case 2:
susStart = hSpace.min + atkEnd;
susPeriod = hSpace.max - hSpace.min;
break;
}
}
}
}
public Param calc()
{
return calc( stream.getTime(), frameLength );
}
public Param calc( double x )
{
return calc( x, frameLength );
}
public Param calc( double x, double width )
{
Curve c = null;
double modDepth = 0.0;
Param mod;
if( x >= atkEnd ) {
if( x >= rlsStart ) {
c = curve[ 1 ];
x -= rlsStart;
} else {
c = curve[ 2 ];
x = (x - susStart) % susPeriod;
}
} else {
c = curve[ 0 ];
x -= atkStart;
}
if( c != null ) {
// dub it. rub it. right on!!!
modDepth = Curve.average( c, x, x + width ) / 100; // % ==> 0...1
mod = Param.transform( new Param( depth.value * modDepth, depth.unit ), env.hUnit,
base, stream );
if( mod != null ) {
return mod;
}
}
return base; // no modulation
}
}
// class Modulator