/* * Warp.java * JCollider * * Copyright (c) 2004-2010 Hanns Holger Rutz. All rights reserved. * * This software 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, june 1991 of the License, or (at your option) any later version. * * This software 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 (gpl.txt) along with this software; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * * For further information, please contact Hanns Holger Rutz at * contact@sciss.de , or visit http://www.sciss.de/jcollider * * * JCollider is closely modelled after SuperCollider Language, * often exhibiting a direct translation from Smalltalk to Java. * SCLang is a software originally developed by James McCartney, * which has become an Open Source project. * See http://www.audiosynth.com/ for details. * * * Changelog: * 29-Jul-06 created */ package de.sciss.jcollider.gui; /** * Helper classes for warping a control value. * This is a quite direct translation from the SClang classes. * * @version 0.28, 29-Jul-06 * @author Hanns Holger Rutz * * @see ControlSpec */ public abstract class Warp { public static Warp lin = new LinearWarp(); public static Warp exp = new ExponentialWarp(); public static Warp sin = new SineWarp(); public static Warp cos = new CosineWarp(); // public static Warp amp = new FaderWarp(); // public static Warp db = new DbFaderWarp(); public static Warp curve( double curve ) { if( curve == 0.0 ) { return lin; } else { return new CurveWarp( curve ); } } public abstract double map( double value, ControlSpec spec ); public abstract double unmap( double value, ControlSpec spec ); private static class LinearWarp extends Warp { protected LinearWarp() { /* empty */ } public double map( double value, ControlSpec spec ) { return( value * spec.getRange() + spec.getMinVal() ); } public double unmap( double value, ControlSpec spec ) { final double range = spec.getRange(); if( range == 0.0 ) { return 0.0; } else { return(( value - spec.getMinVal() ) / range ); } } } // minval and maxval must both be non zero and have the same sign. private static class ExponentialWarp extends Warp { protected ExponentialWarp() { /* empty */ } public double map( double value, ControlSpec spec ) { return( Math.pow( spec.getRatio(), value ) * spec.getMinVal() ); } public double unmap( double value, ControlSpec spec ) { return( Math.log( value / spec.getMinVal() ) / Math.log( spec.getRatio() )); } } private static class SineWarp extends Warp { private static final double PIH = Math.PI * 0.5; protected SineWarp() { /* empty */ } public double map( double value, ControlSpec spec ) { return( Math.sin( PIH * value ) * spec.getRange() + spec.getMinVal() ); } public double unmap( double value, ControlSpec spec ) { final double range = spec.getRange(); if( range == 0.0 ) { return 0.0; } else { return( Math.asin(( value - spec.getMinVal() ) / range ) / PIH ); } } } private static class CosineWarp extends Warp { private static final double PIH = Math.PI * 0.5; protected CosineWarp() { /* empty */ } public double map( double value, ControlSpec spec ) { return( (0.5 - Math.cos( Math.PI * value ) * 0.5) * spec.getRange() + spec.getMinVal() ); } public double unmap( double value, ControlSpec spec ) { final double range = spec.getRange(); if( range == 0.0 ) { return 0.0; } else { return( Math.acos( 1.0 - (( value - spec.getMinVal() ) / range ) * 2.0 ) / PIH ); } } } private static class CurveWarp extends Warp { private final double curve; private final double grow; private final double oneByOneMGrow; protected CurveWarp( double curve ) { this.curve = curve; grow = Math.exp( curve ); oneByOneMGrow = 1.0 / (1.0 - grow); } public double map( double value, ControlSpec spec ) { final double a = spec.getRange() * oneByOneMGrow; final double b = spec.getMinVal() + a; return( b - a * Math.pow( grow, value )); } public double unmap( double value, ControlSpec spec ) { final double a = spec.getRange() * oneByOneMGrow; final double b = spec.getMinVal() + a; return( Math.log(( b - value ) / a ) / curve ); } } }