annotate src/uk/ac/qmul/eecs/depic/patterns/MathUtils.java @ 4:473da40f3d39 tip

added html formatting to Daw/package-info.java
author Fiore Martin <f.martin@qmul.ac.uk>
date Thu, 25 Feb 2016 17:50:09 +0000
parents 629262395647
children
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@1 21 /** Utilities for math operations */
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@1 60 /**
f@1 61 *
f@1 62 * Scales a float from one range of values to another. The scaling can be either lineas or exponential.
f@1 63 *
f@1 64 */
f@0 65 public static class Scale {
f@0 66 private Range<java.lang.Float> from;
f@0 67 private Range<java.lang.Float> to;
f@0 68
f@0 69 public Scale(Range<java.lang.Float> rangeFrom, Range<java.lang.Float> rangeTo) {
f@0 70 this.from = rangeFrom;
f@0 71 this.to = rangeTo;
f@0 72 }
f@0 73
f@0 74 public Scale(float startFrom, float endFrom,float startTo, float endTo) {
f@0 75 this(new Range<java.lang.Float>(startFrom,endFrom),new Range<java.lang.Float>(startTo,endTo));
f@0 76 }
f@0 77
f@0 78 public float linear(float num){
f@0 79 if(Float.compare(num, from.getStart()) < 0 || Float.compare(num,from.getEnd()) > 0)
f@0 80 throw new IllegalArgumentException("num must be in rangeFrom interval. num:"+num+" rangeFrom:"+from);
f@0 81
f@0 82 float ratio = (num - from.getStart()) / from.lenght();
f@0 83
f@0 84 return to.getStart() + (ratio * to.lenght());
f@0 85 }
f@0 86
f@0 87 public float exponential(float num){
f@0 88 if(Float.compare(num, from.getStart()) < 0 || Float.compare(num,from.getEnd()) > 0)
f@0 89 throw new IllegalArgumentException("num must be in rangeFrom interval. num:"+num+" rangeFrom:"+from);
f@0 90
f@0 91 if(Float.compare(to.getStart(),0) == 0 )
f@0 92 throw new IllegalArgumentException("Cannot call esponential when destination range starts from 0");
f@0 93
f@0 94 num = (num - from.getStart())/ from.lenght();
f@0 95
f@0 96 float toRatio = to.getEnd() / to.getStart();
f@0 97 return (float) (Math.pow(toRatio,num) * to.getStart());
f@0 98 }
f@0 99 }
f@0 100
f@0 101 /**
f@0 102 *
f@0 103 * Calculates values at any time in a sequence by interpolating the sequence values.
f@0 104 *
f@0 105 * A sequence is a finite series of float values at given times. In order to get values
f@0 106 * at any times, interpolation is necessary. This class can be useful to build a graph out of
f@0 107 * the sequence values. Of course, as the interpolation changes, the graph changes as well, as
f@0 108 * values at times different from those specified by the sequence will be calculated differently.
f@0 109 *
f@0 110 */
f@0 111 public static class Interpolate {
f@0 112 private Sequence sequence;
f@0 113
f@0 114 public Interpolate(Sequence sequence){
f@0 115 this.sequence = sequence;
f@0 116 }
f@0 117
f@0 118 public float linear(float time){
f@0 119 /* initialise with start and end of the sequence */
f@0 120 float startValue = sequence.getBegin();
f@0 121 float endValue = sequence.getEnd();
f@0 122 float startTimePos = 0;
f@0 123 float endTimePos = sequence.getLen();
f@0 124
f@0 125
f@0 126 for(int i=0; i<sequence.getValuesNum(); i++){
f@0 127 Sequence.Value sv = sequence.getValueAt(i);
f@0 128
f@0 129 if(Float.compare(time, sv.getTimePosition()) >= 0){
f@0 130 startValue = sv.getValue();
f@0 131 startTimePos = sv.getTimePosition();
f@0 132 }
f@0 133
f@0 134 if(Float.compare(time, sv.getTimePosition()) <= 0){
f@0 135 endValue = sv.getValue();
f@0 136 endTimePos = sv.getTimePosition();
f@0 137 break; // can break because values are ordered by time
f@0 138 }
f@0 139 }
f@0 140
f@0 141 /* let D be the distance between time and start, then ratio *
f@0 142 * is the ratio between D and the start-end interval length *
f@0 143 * if startTimepos and endtimePos the ratio is going to be 0*/
f@0 144 float ratio = MathUtils.equal(startTimePos, endTimePos) ? 0.0f : ((time - startTimePos) / (endTimePos-startTimePos));
f@0 145
f@0 146
f@0 147 /* this comes from the following formula:
f@0 148 * valueAtTime = start.getValue + (ratio * (end.getValue() - start.getValue()) */
f@0 149 float valueAtTime = (1.0f - ratio) * startValue + ratio * endValue;
f@0 150
f@0 151 return valueAtTime;
f@0 152 }
f@0 153
f@0 154 }
f@0 155 }