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