merged slee's lx changes
[SugarCubes.git] / Audio.pde
CommitLineData
4c006f7b
MS
1/**
2 * This is a reusable equalizer class that lets you get averaged
3 * bands with dB scaling and smoothing.
4 */
5public static class GraphicEQ {
6
d12e46b6 7 private final LX lx;
4c006f7b
MS
8
9 public final BasicParameter level = new BasicParameter("LVL", 0.5);
10 public final BasicParameter range = new BasicParameter("RNGE", 0.5);
11 public final BasicParameter slope = new BasicParameter("SLOP", 0.5);
12 public final BasicParameter attack = new BasicParameter("ATK", 0.5);
13 public final BasicParameter release = new BasicParameter("REL", 0.5);
14
15 private final FFT fft;
16 private final int numBands;
17
18 private final LinearEnvelope[] bandVals;
19
20 public final static int DEFAULT_NUM_BANDS = 16;
21
d12e46b6 22 public GraphicEQ(LX lx) {
4c006f7b
MS
23 this(lx, DEFAULT_NUM_BANDS);
24 }
25
26 /**
27 * Note that the number of bands is a suggestion. Due to the FFT implementation
28 * the actual number may be slightly different.
29 */
d12e46b6 30 public GraphicEQ(LX lx, int num) {
4c006f7b
MS
31 this.lx = lx;
32 fft = new FFT(lx.audioInput().bufferSize(), lx.audioInput().sampleRate());
33 fft.window(FFT.HAMMING);
34 fft.logAverages(50, num/8);
35 numBands = this.fft.avgSize();
36 bandVals = new LinearEnvelope[numBands];
37 for (int i = 0; i < bandVals.length; ++i) {
922def98 38 (bandVals[i] = new LinearEnvelope(0, 0, 500)).trigger();
4c006f7b
MS
39 }
40 }
41
4760e696
MS
42 static final float logTen = log(10);
43 public static float log10(float val) {
4c006f7b
MS
44 return log(val) / logTen;
45 }
46
47 public float getLevel(int band) {
48 return bandVals[band].getValuef();
49 }
50
51 public float getAverageLevel(int minBand, int numBands) {
52 float avg = 0;
53 for (int i = minBand; i < minBand + numBands; ++i) {
54 avg += bandVals[i].getValuef();
55 }
56 avg /= numBands;
57 return avg;
58 }
59
34327c96 60 public void run(double deltaMs) {
4c006f7b
MS
61 fft.forward(lx.audioInput().mix);
62 float zeroDBReference = pow(10, 100*(1-level.getValuef())/20.);
63 float decibelRange = 12 + range.getValuef() * 60;
64 float decibelSlope = slope.getValuef() * 60.f / numBands;
65 for (int i = 0; i < numBands; ++i) {
66 float raw = fft.getAvg(i);
67 float decibels = 20*log10(raw / zeroDBReference);
68 float positiveDecibels = decibels + decibelRange;
69 positiveDecibels += i*decibelSlope;
70 float value = constrain(positiveDecibels / decibelRange, 0, 1);
71
72 if (value > bandVals[i].getValuef()) {
4760e696 73 bandVals[i].setRangeFromHereTo(value, attack.getValuef() * 20).trigger();
4c006f7b
MS
74 }
75 }
76 for (LinearEnvelope band : bandVals) {
77 band.run(deltaMs);
78 if (!band.isRunning() && band.getValuef() > 0) {
4760e696 79 band.setRangeFromHereTo(0, release.getValuef() * 1600).trigger();
4c006f7b
MS
80 }
81 }
82 }
83}
84
85