Mercurial > hg > cmdp
view src/uk/ac/qmul/eecs/depic/patterns/MathUtils.java @ 1:629262395647
Added some dosumentation
added .hginfo
author | Fiore Martin <f.martin@qmul.ac.uk> |
---|---|
date | Wed, 17 Feb 2016 14:43:35 +0000 |
parents | 3074a84ef81e |
children |
line wrap: on
line source
/* Cross-Modal DAW Prototype - Prototype of a simple Cross-Modal Digital Audio Workstation. Copyright (C) 2015 Queen Mary University of London (http://depic.eecs.qmul.ac.uk/) This program 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 3 of the License, or (at your option) any later version. This program 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 this program. If not, see <http://www.gnu.org/licenses/>. */ package uk.ac.qmul.eecs.depic.patterns; /** Utilities for math operations */ public class MathUtils { public static boolean equal(float a, float b){ return Float.compare(a, b) == 0; } public static boolean equal(double a, double b){ return Double.compare(a, b) == 0 ; } public static boolean equal(float a, float b , float epsilon){ return Math.abs(a-b) < epsilon; } public static boolean equal(double a, double b , double epsilon){ return Math.abs(a-b) < epsilon; } /** * * @param amp amplitude value in the normalized form (ranging from 0 to 1) * * @return the decibel conversion of {@code amp} */ public static float toDb(float amp){ if(Float.compare(amp,0) < 0){ throw new RuntimeException(); } return (float)(20.0 * Math.log10(amp)); } public static float toAmp(float db){ return (float) (Math.pow(10, db/ 20.0)); } /** * * Scales a float from one range of values to another. The scaling can be either lineas or exponential. * */ public static class Scale { private Range<java.lang.Float> from; private Range<java.lang.Float> to; public Scale(Range<java.lang.Float> rangeFrom, Range<java.lang.Float> rangeTo) { this.from = rangeFrom; this.to = rangeTo; } public Scale(float startFrom, float endFrom,float startTo, float endTo) { this(new Range<java.lang.Float>(startFrom,endFrom),new Range<java.lang.Float>(startTo,endTo)); } public float linear(float num){ if(Float.compare(num, from.getStart()) < 0 || Float.compare(num,from.getEnd()) > 0) throw new IllegalArgumentException("num must be in rangeFrom interval. num:"+num+" rangeFrom:"+from); float ratio = (num - from.getStart()) / from.lenght(); return to.getStart() + (ratio * to.lenght()); } public float exponential(float num){ if(Float.compare(num, from.getStart()) < 0 || Float.compare(num,from.getEnd()) > 0) throw new IllegalArgumentException("num must be in rangeFrom interval. num:"+num+" rangeFrom:"+from); if(Float.compare(to.getStart(),0) == 0 ) throw new IllegalArgumentException("Cannot call esponential when destination range starts from 0"); num = (num - from.getStart())/ from.lenght(); float toRatio = to.getEnd() / to.getStart(); return (float) (Math.pow(toRatio,num) * to.getStart()); } } /** * * Calculates values at any time in a sequence by interpolating the sequence values. * * A sequence is a finite series of float values at given times. In order to get values * at any times, interpolation is necessary. This class can be useful to build a graph out of * the sequence values. Of course, as the interpolation changes, the graph changes as well, as * values at times different from those specified by the sequence will be calculated differently. * */ public static class Interpolate { private Sequence sequence; public Interpolate(Sequence sequence){ this.sequence = sequence; } public float linear(float time){ /* initialise with start and end of the sequence */ float startValue = sequence.getBegin(); float endValue = sequence.getEnd(); float startTimePos = 0; float endTimePos = sequence.getLen(); for(int i=0; i<sequence.getValuesNum(); i++){ Sequence.Value sv = sequence.getValueAt(i); if(Float.compare(time, sv.getTimePosition()) >= 0){ startValue = sv.getValue(); startTimePos = sv.getTimePosition(); } if(Float.compare(time, sv.getTimePosition()) <= 0){ endValue = sv.getValue(); endTimePos = sv.getTimePosition(); break; // can break because values are ordered by time } } /* let D be the distance between time and start, then ratio * * is the ratio between D and the start-end interval length * * if startTimepos and endtimePos the ratio is going to be 0*/ float ratio = MathUtils.equal(startTimePos, endTimePos) ? 0.0f : ((time - startTimePos) / (endTimePos-startTimePos)); /* this comes from the following formula: * valueAtTime = start.getValue + (ratio * (end.getValue() - start.getValue()) */ float valueAtTime = (1.0f - ratio) * startValue + ratio * endValue; return valueAtTime; } } }