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;
+		}
+		
+	}
+}