This repository was archived by the owner on Mar 8, 2026. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathInterpolatedSpectrum.pde
More file actions
139 lines (119 loc) · 3.75 KB
/
InterpolatedSpectrum.pde
File metadata and controls
139 lines (119 loc) · 3.75 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
static float LN10 = 2.30258509299f;
class InterpolatedSpectrum {
public boolean logScaleFreq = false;
public float coefFreq = 1f;
public boolean logScalePower = true;
public float coefPower = 1f;
public boolean interpolation = true;
public float interpolateRange = 1f;
private FFT fft;
private int specSize;
private float[] spectrum;
private float maxPower;
public void setFFT(FFT fft) {
this.fft = fft;
this.specSize = fft.specSize();
this.spectrum = new float[specSize];
// calculate an integrated window function
float[] wbuf = new float[fft.timeSize()];
for (int i = 0; i < fft.timeSize(); ++i) wbuf[i] = 1f;
FFT wfft = new FFT(fft.timeSize(), 44100);
wfft.forward(wbuf);
wfft.inverse(wbuf);
this.maxPower = 0f;
for (int i = 0; i < fft.timeSize(); ++i) this.maxPower += wbuf[i];
}
public void load(FFT fft) {
if (this.fft != fft) this.setFFT(fft);
for (int i = 0; i < this.specSize; ++i) spectrum[i] = fft.getBand(i);
}
public float getPower(float index) {
float power = 0f;
if (this.interpolation && index < this.specSize*interpolateRange) {
// Lanczos-3 Interpolate
int bFil = floor(index) - 2;
if (bFil < 0) bFil = 0;
int eFil = bFil + 5;
if (eFil > this.specSize) eFil = this.specSize;
for (int i = bFil; i < eFil; ++i) {
power += this.spectrum[i] * lanczos3(index - i);
}
} else {
power = this.spectrum[floor(index)];
}
power *= this.coefPower;
return this.convertPowerToLinOrLog(power);
}
public float getMaxPower(float beginIndex, float endIndex) {
if (endIndex-beginIndex < 0) {
float tmp = beginIndex;
beginIndex = endIndex;
endIndex = tmp;
}
if (endIndex-beginIndex < 1f) {
return this.getPower(endIndex);
}
float power = 0f;
int floorBeginIndex = floor(beginIndex);
if (beginIndex > floorBeginIndex) {
if (this.interpolation && floorBeginIndex < this.specSize*interpolateRange) {
// Lanczos-3 Interpolate
int bFil = floor(beginIndex) - 2;
if (bFil < 0) bFil = 0;
int eFil = bFil + 5;
if (eFil > this.specSize) eFil = this.specSize;
for (int i = bFil; i < eFil; ++i) {
power += this.spectrum[i] * lanczos3(beginIndex - i);
}
} else {
power = this.spectrum[floorBeginIndex];
}
}
for (int i = ceil(beginIndex); i < endIndex; i++) {
power = max(power, this.spectrum[i]);
}
return this.convertPowerToLinOrLog(power);
}
public float getIndex(float g) {
g *= this.coefFreq;
float index = 0f;
if (this.logScaleFreq) {
// map from 0~1 to {Band width}~{SR/2}Hz
index = pow(this.specSize, g);
} else {
index = g * this.specSize;
}
if (index < 0) index = 0;
else if (index >= this.specSize-1) index = this.specSize-1;
return index;
}
public float indexToFreq(float index) {
return this.fft.getBandWidth() * index;
}
public float dbPower(float power) {
if (this.logScalePower) {
if (Float.isFinite(power)) {
power = pow(maxPower, power) / this.maxPower;
} else {
return Float.NEGATIVE_INFINITY;
}
}
return 20f * log(power / this.coefPower) / LN10;
}
protected float sinc_PI(float x) {
if (x == 0) return 1f;
else return sin(PI*x) / (PI*x);
}
protected float lanczos3(float x) {
if (x <= -3 || x >= 3) return 0f;
else return sinc_PI(x) * sinc_PI(x/3);
}
private float convertPowerToLinOrLog(float power) {
if (this.logScalePower) {
//if (power <= 1) power = 0f; // enabled signal filter
return log(power) / log(this.maxPower);
} else {
return power / this.maxPower;
}
}
}