-
Notifications
You must be signed in to change notification settings - Fork 28
/
AudioInputBeads.java
183 lines (155 loc) · 5.55 KB
/
AudioInputBeads.java
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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
package com.haxademic.core.media.audio.analysis;
import java.util.Iterator;
import java.util.Set;
import com.haxademic.core.app.P;
import com.haxademic.core.media.audio.AudioUtil;
import beads.AudioContext;
import beads.Bead;
import beads.BiquadFilter;
import beads.FFT;
import beads.Gain;
import beads.PeakDetector;
import beads.PowerSpectrum;
import beads.RampBuffer;
import beads.ShortFrameSegmenter;
import beads.SpectralDifference;
import beads.UGen;
import processing.core.PGraphics;
public class AudioInputBeads
implements IAudioInput {
protected AudioContext ac;
protected Gain gain;
protected int FFT_SIZE = 512;
protected float[] freqs = new float[FFT_SIZE/2];
protected ShortFrameSegmenter sfs;
protected FFT fft;
protected PowerSpectrum ps;
protected PeakDetector od;
protected BiquadFilter fftFilter;
protected AudioStreamData audioStreamData = new AudioStreamData();
protected boolean beatDirty = false;
protected int beatTimeThresh = 300;
protected int lastBeatTime = 0;
protected boolean audioInput = true;
public AudioInputBeads() {
ac = AudioUtil.getBeadsContext();
sfs = new ShortFrameSegmenter(ac);
gain = new Gain(ac, 2);
fft = new FFT();
ps = new PowerSpectrum();
sfs.setChunkSize(FFT_SIZE);
sfs.setHopSize(FFT_SIZE/2);
sfs.addInput(gain); // sfs.addInput(ac.out);
sfs.addListener(fft);
fft.addListener(ps);
ac.out.addDependent(sfs);
addBeatDetection();
// common setup and stream init
gain.addInput(ac.getAudioInput());
ac.start();
// make sure we have analysis arrays created
audioStreamData.setFFTFrequencies(freqs);
}
public AudioInputBeads(AudioContext exsitingAc) {
ac = exsitingAc;
audioInput = false;
// make a filter to chill out the lowest frequencies of an audio file
// fftFilter = new BiquadFilter(ac, BiquadFilter.BP_PEAK, 1900.0f, 0.6f);// connect the SamplePlayer to the filterfilter1.addInput(sp);
fftFilter = new BiquadFilter(ac, BiquadFilter.BP_PEAK, 5000.0f, 0.7f);// connect the SamplePlayer to the filterfilter1.addInput(sp);
fftFilter.addInput(ac.out);
sfs = new ShortFrameSegmenter(ac);
gain = new Gain(ac, 2);
fft = new FFT();
ps = new PowerSpectrum();
sfs.setChunkSize(FFT_SIZE);
sfs.setHopSize(FFT_SIZE/2);
sfs.addInput(gain); // fftFilter // sfs.addInput(ac.out);
sfs.addListener(fft);
fft.addListener(ps);
ac.out.addDependent(sfs);
gain.addInput(ac.out);
addBeatDetection();
// make sure we have analysis arrays created
audioStreamData.setFFTFrequencies(freqs);
}
public void addInput(UGen input) {
// remove inputs to make way for a new one
Set<UGen> ins = sfs.getConnectedInputs();
Iterator<UGen> itr = ins.iterator();
while(itr.hasNext()){
UGen in = itr.next();
sfs.removeAllConnections(in);
}
// add new input!
// P.out("sfs.noInputs()", sfs.noInputs());
sfs.addInput(input);
}
public void addBeatDetection() {
// beat detection
SpectralDifference sd = new SpectralDifference(ac.getSampleRate());
ps.addListener(sd);
od = new PeakDetector();
sd.addListener(od);
od.setThreshold(0.85f);
od.setResetDelay(250);
od.setAlpha(0.1f);
od.setFilter(new RampBuffer().generateBuffer(64));
od.addMessageListener( new Bead() {
protected void messageReceived(Bead b) {
beatDirty = true;
}
});
}
// update methods -------------------------------------
public AudioStreamData audioData() { return audioStreamData; }
public PGraphics debugBuffer() { return audioStreamData.debugBuffer; }
public void drawDebugBuffer() { audioStreamData.drawDebug(); }
public void drawDataBuffers() {
audioStreamData.drawBufferFFT();
audioStreamData.drawBufferWaveform();
}
public void update() {
// get FFT spectrum from Beads
if(ps == null) return;
float[] features = ps.getFeatures();
// update audio data object
if(features != null) {
// make a lower-amplitude copy
int hopSize = FFT_SIZE / 2;
for (int i = 0; i < hopSize; i++) {
freqs[i] = features[i] * 5f * window(hopSize, i);
}
audioStreamData.setFFTFrequencies(freqs);
audioStreamData.calcFreqsDampened();
}
// if(audioInput) {
audioStreamData.setWaveformOffsets(gain.getOutBuffer(0));
// } else {
// audioStreamData.setWaveformOffsets(ac.out.getOutBuffer(0));
// }
if(beatDirty && P.p.millis() > lastBeatTime + beatTimeThresh) {
lastBeatTime = P.p.millis();
beatDirty = false;
audioStreamData.setBeat();
}
// audioStreamData.setAmp(od.getLastOnsetValue());
audioStreamData.calcAmpAverage();
audioStreamData.update();
}
protected float window(int length, int index) {
//float alpha = 0.25f;
// bartlett-hann window
return (float) (0.62f - 0.48f * P.abs(index / (length - 1) - 0.5f) - 0.38f * P.cos(P.TWO_PI * index / (length - 1f)));
// bartlett window:
// return 2f / (length - 1) * ((length - 1) / 2f - Math.abs(index - (length - 1) / 2f));
// blackman window: https://github.com/ddf/Minim/blob/master/src/main/java/ddf/minim/analysis/BlackmanWindow.java
// float a0 = (1 - alpha) / 2f;
// float a1 = 0.5f;
// float a2 = alpha / 2f;
// return a0 - a1 * (float) P.cos(P.TWO_PI * index / (length - 1)) + a2 * (float) P.cos(4f * P.PI * index / (length - 1));
// triangle window: https://github.com/ddf/Minim/blob/master/src/main/java/ddf/minim/analysis/TriangularWindow.java
// return 2f / length * (length / 2f - Math.abs(index - (length - 1) / 2f));
// gauss window: https://github.com/ddf/Minim/blob/master/src/main/java/ddf/minim/analysis/GaussWindow.java
// return (float) Math.pow(Math.E, -0.5 * Math.pow((index - (length - 1) / (double) 2) / (alpha * (length - 1) / (double) 2), (double) 2));
}
}