/* Copyright (C) 2007 Julien Pauty
*
* This file is part of Nomad.
*
* Nomad 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.
*
* Nomad 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 Nomad; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.sf.nmedit.jtheme.clavia.nordmodular.graphics;
import java.awt.geom.PathIterator;
public class Compressor extends Curve {
int limiterInt = 12;
float ratio = 1.0f,refLevel = 0.5f,limiter = limiterInt/42f,threshold;
int ratioIndex = 0;
public Compressor(){
super(6);
points[0].setPoint_type(PathIterator.SEG_MOVETO);
points[0].setLocation(-0.1f,1f);
update();
}
private void update(){
setModified(true);
if(threshold <= refLevel){
//refLevel point statifies equation: 1-refLevel= -ratio*refLevel +b
float b = (1-refLevel) + ratio*(refLevel);
// attenuation line passes through refLevel points and
// intersect with y=limiter at : x = (limiter -b)/ratio
float xLimiter = (limiter -b)/-ratio;
float yThresh = -ratio*threshold+b;
// handling case when threshold is > limiter
if(yThresh >= limiter) {
// first segment equation is y=-x + yThresh + threshold
points[0].setLocation(-1, 1+yThresh+threshold);
points[1].setLocation(threshold, yThresh);
points[1].setPoint_type(PathIterator.SEG_LINETO);
//beginning of the limiter horizontal line
points[2].setLocation(xLimiter, limiter);
points[2].setPoint_type(PathIterator.SEG_LINETO);
}
else {
// in this case we have no attenuation line,
// so point[1] and point [2] have the same coordinates
if (threshold <= 1-limiter) {
//first segment equation is y=-x + yThresh + threshold
points[0].setLocation(-1, 1+limiter+threshold);
points[1].setLocation(threshold, limiter);
points[1].setPoint_type(PathIterator.SEG_LINETO);
//beginning of the limiter horizontal line
points[2].setLocation(threshold, limiter);
points[2].setPoint_type(PathIterator.SEG_LINETO);
}
// threshold line follows the y=1-x line
else{
//first segment equation is y=-x + yThresh + threshold
points[0].setLocation(0, 1);
points[1].setLocation(1f - limiter, limiter);
points[1].setPoint_type(PathIterator.SEG_LINETO);
//beginning of the limiter horizontal line
points[2].setLocation(1 - limiter, limiter);
points[2].setPoint_type(PathIterator.SEG_LINETO);
}
}
points[3].setLocation(2, limiter);
points[3].setPoint_type(PathIterator.SEG_LINETO);
} else {
// refLevel point statifies equation: 1-refLevel= -ratio*refLevel +b
float tempThresh = threshold >= (1-limiter) ? 1-limiter : threshold;
float b = (1-tempThresh) + ratio*(tempThresh);
// attenuation line passes through refLevel points and
// intersect with y=limiter at : x = (limiter -b)/ratio
float xLimiter = (limiter -b)/-ratio;
points[0].setLocation(0, 1);
//TODO: there is a minor graphical glitch due to rounding
// errors => (1-tempThresh)+tempThresh != 1
points[1].setLocation(tempThresh, 1f-tempThresh);
points[1].setPoint_type(PathIterator.SEG_LINETO);
points[2].setLocation(xLimiter, limiter);
points[2].setPoint_type(PathIterator.SEG_LINETO);
points[3].setLocation(2, limiter);
points[3].setPoint_type(PathIterator.SEG_LINETO);
}
points[4].setLocation(2, 2);
points[5].setLocation(2, 2);
}
public int getLimiter() {
return limiterInt;
}
public void setLimiter(int limiter) {
this.limiterInt = limiter;
this.limiter = 24f/42f-limiter/42f;
update();
}
public float getRatio() {
return ratioIndex;
}
public void setRatio(int ratio) {
this.ratio = 1.0f/_convert_ratio(ratio);
this.ratioIndex = ratio;
update();
}
public float getRefLevel() {
return refLevel;
}
public void setRefLevel(float refLevel) {
this.refLevel = refLevel;
update();
}
public float getThreshold() {
return threshold;
}
public void setThreshold(float threshold) {
this.threshold = threshold;
update();
}
private float _convert_ratio(int ratio){
float conv[] = {1.0f,1.1f,1.2f,1.3f,1.4f,1.5f,1.6f,1.7f,1.8f,1.9f,2.0f,2.2f,2.4f,2.6f,2.8f,3.0f,3.2f,3.4f,3.6f,3.8f,4.0f,4.2f,4.4f,4.6f,4.8f,5.0f,5.5f,6.0f,6.5f,7.0f,7.5f,8.0f,8.5f,9.0f,9.5f,10f,11f,12f,13f,14f,15f,16f,17f,18f,19f,20f,22f,24f,26f,28f,30f,32f,34f,36f,38f,40f,42f,44f,46f,48f,50f,55f,60f,65f,70f,75f,80f};
return ratio < conv.length ? conv[ratio]: 1.0f;
}
}