annotate 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
rev   line source
f@0 1 /*
f@0 2 Cross-Modal DAW Prototype - Prototype of a simple Cross-Modal Digital Audio Workstation.
f@0 3
f@0 4 Copyright (C) 2015 Queen Mary University of London (http://depic.eecs.qmul.ac.uk/)
f@0 5
f@0 6 This program is free software: you can redistribute it and/or modify
f@0 7 it under the terms of the GNU General Public License as published by
f@0 8 the Free Software Foundation, either version 3 of the License, or
f@0 9 (at your option) any later version.
f@0 10
f@0 11 This program is distributed in the hope that it will be useful,
f@0 12 but WITHOUT ANY WARRANTY; without even the implied warranty of
f@0 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
f@0 14 GNU General Public License for more details.
f@0 15
f@0 16 You should have received a copy of the GNU General Public License
f@0 17 along with this program. If not, see <http://www.gnu.org/licenses/>.
f@0 18 */
f@0 19 package uk.ac.qmul.eecs.depic.patterns;
f@0 20
f@0 21
f@0 22 public class MathUtils {
f@0 23
f@0 24 public static boolean equal(float a, float b){
f@0 25 return Float.compare(a, b) == 0;
f@0 26 }
f@0 27
f@0 28 public static boolean equal(double a, double b){
f@0 29 return Double.compare(a, b) == 0 ;
f@0 30
f@0 31 }
f@0 32
f@0 33 public static boolean equal(float a, float b , float epsilon){
f@0 34 return Math.abs(a-b) < epsilon;
f@0 35 }
f@0 36
f@0 37 public static boolean equal(double a, double b , double epsilon){
f@0 38 return Math.abs(a-b) < epsilon;
f@0 39 }
f@0 40
f@0 41
f@0 42 /**
f@0 43 *
f@0 44 * @param amp amplitude value in the normalized form (ranging from 0 to 1)
f@0 45 *
f@0 46 * @return the decibel conversion of {@code amp}
f@0 47 */
f@0 48 public static float toDb(float amp){
f@0 49 if(Float.compare(amp,0) < 0){
f@0 50 throw new RuntimeException();
f@0 51 }
f@0 52
f@0 53 return (float)(20.0 * Math.log10(amp));
f@0 54 }
f@0 55
f@0 56 public static float toAmp(float db){
f@0 57 return (float) (Math.pow(10, db/ 20.0));
f@0 58 }
f@0 59
f@0 60
f@0 61 public static class Scale {
f@0 62 private Range<java.lang.Float> from;
f@0 63 private Range<java.lang.Float> to;
f@0 64
f@0 65 public Scale(Range<java.lang.Float> rangeFrom, Range<java.lang.Float> rangeTo) {
f@0 66 this.from = rangeFrom;
f@0 67 this.to = rangeTo;
f@0 68 }
f@0 69
f@0 70 public Scale(float startFrom, float endFrom,float startTo, float endTo) {
f@0 71 this(new Range<java.lang.Float>(startFrom,endFrom),new Range<java.lang.Float>(startTo,endTo));
f@0 72 }
f@0 73
f@0 74 public float linear(float num){
f@0 75 if(Float.compare(num, from.getStart()) < 0 || Float.compare(num,from.getEnd()) > 0)
f@0 76 throw new IllegalArgumentException("num must be in rangeFrom interval. num:"+num+" rangeFrom:"+from);
f@0 77
f@0 78 float ratio = (num - from.getStart()) / from.lenght();
f@0 79
f@0 80 return to.getStart() + (ratio * to.lenght());
f@0 81 }
f@0 82
f@0 83 public float exponential(float num){
f@0 84 if(Float.compare(num, from.getStart()) < 0 || Float.compare(num,from.getEnd()) > 0)
f@0 85 throw new IllegalArgumentException("num must be in rangeFrom interval. num:"+num+" rangeFrom:"+from);
f@0 86
f@0 87 if(Float.compare(to.getStart(),0) == 0 )
f@0 88 throw new IllegalArgumentException("Cannot call esponential when destination range starts from 0");
f@0 89
f@0 90 num = (num - from.getStart())/ from.lenght();
f@0 91
f@0 92 float toRatio = to.getEnd() / to.getStart();
f@0 93 return (float) (Math.pow(toRatio,num) * to.getStart());
f@0 94 }
f@0 95 }
f@0 96
f@0 97 /**
f@0 98 *
f@0 99 * Calculates values at any time in a sequence by interpolating the sequence values.
f@0 100 *
f@0 101 * A sequence is a finite series of float values at given times. In order to get values
f@0 102 * at any times, interpolation is necessary. This class can be useful to build a graph out of
f@0 103 * the sequence values. Of course, as the interpolation changes, the graph changes as well, as
f@0 104 * values at times different from those specified by the sequence will be calculated differently.
f@0 105 *
f@0 106 */
f@0 107 public static class Interpolate {
f@0 108 private Sequence sequence;
f@0 109
f@0 110 public Interpolate(Sequence sequence){
f@0 111 this.sequence = sequence;
f@0 112 }
f@0 113
f@0 114 public float linear(float time){
f@0 115 /* initialise with start and end of the sequence */
f@0 116 float startValue = sequence.getBegin();
f@0 117 float endValue = sequence.getEnd();
f@0 118 float startTimePos = 0;
f@0 119 float endTimePos = sequence.getLen();
f@0 120
f@0 121
f@0 122 for(int i=0; i<sequence.getValuesNum(); i++){
f@0 123 Sequence.Value sv = sequence.getValueAt(i);
f@0 124
f@0 125 if(Float.compare(time, sv.getTimePosition()) >= 0){
f@0 126 startValue = sv.getValue();
f@0 127 startTimePos = sv.getTimePosition();
f@0 128 }
f@0 129
f@0 130 if(Float.compare(time, sv.getTimePosition()) <= 0){
f@0 131 endValue = sv.getValue();
f@0 132 endTimePos = sv.getTimePosition();
f@0 133 break; // can break because values are ordered by time
f@0 134 }
f@0 135 }
f@0 136
f@0 137 /* let D be the distance between time and start, then ratio *
f@0 138 * is the ratio between D and the start-end interval length *
f@0 139 * if startTimepos and endtimePos the ratio is going to be 0*/
f@0 140 float ratio = MathUtils.equal(startTimePos, endTimePos) ? 0.0f : ((time - startTimePos) / (endTimePos-startTimePos));
f@0 141
f@0 142
f@0 143 /* this comes from the following formula:
f@0 144 * valueAtTime = start.getValue + (ratio * (end.getValue() - start.getValue()) */
f@0 145 float valueAtTime = (1.0f - ratio) * startValue + ratio * endValue;
f@0 146
f@0 147 return valueAtTime;
f@0 148 }
f@0 149
f@0 150 }
f@0 151 }