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 package org.openimaj.audio;
31
32 import java.util.ArrayList;
33 import java.util.List;
34
35 import org.openimaj.audio.analysis.FourierTransform;
36 import org.openimaj.audio.processor.AudioProcessor;
37 import org.openimaj.util.pair.IndependentPair;
38 import org.openimaj.util.pair.Pair;
39
40
41
42
43
44
45
46 public class FrequencyAudioSource extends AudioProcessor implements Runnable {
47
48
49
50
51
52
53
54
55 public static interface Listener {
56
57
58
59
60
61
62
63
64
65 public void consumeFrequency(float[] fftReal, float[] fftImag, int low, int high);
66
67 }
68
69 private final FourierTransform fftProc;
70 private final List<IndependentPair<Listener, Pair<Integer>>> listeners;
71 private float[] fftReal;
72 private float[] fftImag;
73
74
75
76
77
78
79 public FrequencyAudioSource(final AudioStream stream) {
80 super(stream);
81 this.fftProc = new FourierTransform();
82 this.listeners = new ArrayList<IndependentPair<Listener, Pair<Integer>>>();
83 new Thread(this).start();
84 }
85
86 @Override
87 public SampleChunk process(final SampleChunk sample) throws Exception {
88 this.fftProc.process(sample);
89 final float[] fft = this.fftProc.getLastFFT()[0];
90 this.fireFrequencyEvent(fft,sample);
91 return sample;
92 }
93
94 private void fireFrequencyEvent(final float[] fft,final SampleChunk sample) {
95 final double binSize = (sample.getFormat().getSampleRateKHz()*1000) / (fft.length/2);
96 if(this.fftReal == null || fft.length/4 != this.fftReal.length){
97 this.fftReal = new float[fft.length/4];
98 this.fftImag = new float[fft.length/4];
99 }
100
101 for( int i = 0; i < fft.length/4; i++ )
102 {
103 final float re = fft[i*2];
104 final float im = fft[i*2+1];
105 this.fftReal[i] = re;
106 this.fftImag[i] = im;
107 }
108 for(final IndependentPair<Listener,Pair<Integer>> l : this.listeners){
109 final Pair<Integer> range = l.secondObject();
110 final int low = (int) (range.firstObject()/binSize);
111 final int high = (int) (range.secondObject()/binSize);
112 l.firstObject().consumeFrequency(this.fftReal,this.fftImag,low,high);
113 }
114 }
115
116 @Override
117 public void run() {
118
119 try
120 {
121 Thread.sleep( 500 );
122 SampleChunk s = null;
123 while( (s = this.nextSampleChunk()) != null ) {
124 this.process( s );
125 }
126 }
127 catch( final InterruptedException e )
128 {
129 e.printStackTrace();
130 }
131 catch (final Exception e)
132 {
133 e.printStackTrace();
134 }
135
136
137 }
138
139
140
141
142
143 public void addFrequencyListener(final Listener l) {
144 final Pair<Integer> range = null;
145 this.listeners.add(IndependentPair.pair(l,range));
146 }
147
148
149
150
151
152
153 public void addFrequencyListener(final Listener l, final Pair<Integer> requestFrequencyRange) {
154 this.listeners.add(IndependentPair.pair(l,requestFrequencyRange));
155 }
156 }