Mercurial > hg > cmdp
diff src/uk/ac/qmul/eecs/depic/patterns/MathUtils.java @ 0:3074a84ef81e
first import
author | Fiore Martin <f.martin@qmul.ac.uk> |
---|---|
date | Wed, 26 Aug 2015 16:16:53 +0100 |
parents | |
children | 629262395647 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/uk/ac/qmul/eecs/depic/patterns/MathUtils.java Wed Aug 26 16:16:53 2015 +0100 @@ -0,0 +1,151 @@ +/* + 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; + + +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)); + } + + + 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; + } + + } +}