@@ -10,25 +10,22 @@ import (
1010
1111// Spectrum is an audio spectrum in a buffer
1212type Spectrum struct {
13- numBins int
14- numStreams int
13+ numBins int
1514
1615 fftSize int
1716
1817 sampleSize int
1918 sampleRate float64
2019
21- gamma float64
20+ winVar float64
2221
23- smoothFact float64
24- smoothResp float64
22+ smoothFactor float64
2523
2624 bins []bin
2725
2826 fftBuf []complex128
2927
30- streams []* stream
31- streamBufs [][]float64
28+ streams []* stream
3229}
3330
3431type bin struct {
@@ -46,6 +43,23 @@ type stream struct {
4643 plan * fft.Plan
4744}
4845
46+ // Frequencies are the dividing frequencies
47+ var Frequencies = []float64 {
48+ // sub sub bass
49+ 20.0 ,
50+ // sub bass
51+ 60.0 ,
52+ // bass
53+ 250.0 ,
54+ // midrange
55+ 4000.0 ,
56+ // treble
57+ 12000.0 ,
58+ // brilliance
59+ 22050.0 ,
60+ // everything else
61+ }
62+
4963// SpectrumType is the type of calculation we run
5064type SpectrumType int
5165
@@ -73,32 +87,63 @@ func NewSpectrum(hz float64, size int) *Spectrum {
7387 var fftSize = (size / 2 ) + 1
7488
7589 var sp = & Spectrum {
76- numBins : size ,
77- fftSize : fftSize ,
78- sampleSize : size ,
79- sampleRate : hz ,
80- smoothFact : 0.255 ,
81- gamma : 4.0 ,
82- bins : make ([]bin , size + 1 ),
83- fftBuf : make ([]complex128 , fftSize ),
84- streams : make ([]* stream , 0 ),
85- streamBufs : make ([][]float64 , 0 ),
90+ fftSize : fftSize ,
91+ sampleSize : size ,
92+ sampleRate : hz ,
93+ smoothFactor : 0.655 ,
94+ winVar : 1.0 ,
95+ bins : make ([]bin , size + 1 ),
96+ fftBuf : make ([]complex128 , fftSize ),
97+ streams : make ([]* stream , 0 , 2 ),
8698 }
8799
88100 return sp
89101}
90102
103+ // StreamCount returns the number of streams in our buffers
104+ func (sp * Spectrum ) StreamCount () int {
105+ return len (sp .streams )
106+ }
107+
108+ // AddStream adds an input buffer to the spectrum
109+ func (sp * Spectrum ) AddStream (input []float64 ) {
110+ var s = & stream {
111+ input : input ,
112+ buf : make ([]float64 , sp .sampleSize ),
113+ pBuf : make ([]float64 , sp .sampleSize ),
114+ plan : fft .NewPlan (input , sp .fftBuf ),
115+ }
116+
117+ sp .streams = append (sp .streams , s )
118+ }
119+
120+ // BinBuffers returns our bin buffers
121+ func (sp * Spectrum ) BinBuffers () [][]float64 {
122+ var buf = make ([][]float64 , len (sp .streams ))
123+ for idx , stream := range sp .streams {
124+ buf [idx ] = stream .buf
125+ }
126+
127+ return buf
128+ }
129+
130+ // BinCount returns the number of bins each stream has
131+ func (sp * Spectrum ) BinCount () int {
132+ return sp .numBins
133+ }
134+
91135// Process makes numBins and dumps them in the buffer
92- func (sp * Spectrum ) Process () {
93- var sf = math .Pow (10.0 , (- ( 1 - sp .smoothFact )) * 10.0 )
136+ func (sp * Spectrum ) Process (win window. Function ) {
137+ var sf = math .Pow (10.0 , (1 - sp .smoothFactor ) * ( - 10.0 ) )
94138
95139 sf = math .Pow (sf , float64 (sp .sampleSize )/ sp .sampleRate )
96140
97- var bassCut = sp .freqToIdx (dividers [2 ], math .Round )
141+ var bassCut = sp .freqToIdx (Frequencies [2 ], math .Round )
142+ var fBassCut = float64 (bassCut )
98143
99144 for _ , stream := range sp .streams {
100145
101- window . Hamming (stream .input , sp . sampleSize )
146+ win (stream .input )
102147
103148 stream .plan .Execute ()
104149
@@ -116,69 +161,62 @@ func (sp *Spectrum) Process() {
116161
117162 // mag /= float64(sp.bins[xB].widthFFT)
118163
119- mag *= sp .bins [xB ].eqVal
164+ var pow = 0.6
165+
120166 switch {
167+ case mag < 0.0 :
168+ mag = 0.0
169+ continue
170+
121171 case sp .bins [xB ].floorFFT < bassCut :
122- mag = math .Pow (mag , 0.5 * (float64 (xF )/ float64 (bassCut )))
172+ pow *= math .Max (0.6 , float64 (xF )/ fBassCut )
173+
123174 default :
124- mag = math . Pow ( mag , 0.6 )
175+ mag *= sp . bins [ xB ]. eqVal
125176 }
126177
127- if mag < 0.0 {
128- mag = 0.0
129- }
178+ mag = math .Pow (mag , pow )
130179
131180 // Smoothing
132181
133- // mag *= (1.0 - sf)
134- // mag += stream.pBuf[xB] * sf
135- // stream.pBuf[xB] = mag
136- // stream.buf[xB] = mag
137-
138- mag += stream .pBuf [xB ] * sp .smoothFact
139- stream .pBuf [xB ] = mag * (1 - (1 / (1 + (mag * 2 ))))
182+ mag *= (1.0 - sf )
183+ mag += stream .pBuf [xB ] * sf
184+ stream .pBuf [xB ] = mag
140185 stream .buf [xB ] = mag
141186
187+ // mag += stream.pBuf[xB] * sp.smoothFactor
188+ // stream.pBuf[xB] = mag * (1 - (1 / (1 + (mag * 2))))
189+ // stream.buf[xB] = mag
190+
142191 }
143192 }
144193}
145194
146- // Frequencies
147- // [0] - Sub - [1] Bass - [2] Mid - [3] - Treble - [4] - Brilliance - [5]
148- var dividers = []float64 {
149- 20.0 ,
150- 60.0 ,
151- 250.0 ,
152- 4000.0 ,
153- 12000.0 ,
154- 22050.0 ,
155- }
156-
157195// Recalculate rebuilds our frequency bins
158196func (sp * Spectrum ) Recalculate (bins int , stype SpectrumType ) int {
159197
160198 switch {
161- case bins == sp .numBins :
162- return bins
163199 case bins >= sp .fftSize :
164200 bins = sp .fftSize - 1
201+ case bins == sp .numBins :
202+ return bins
165203 }
166204
167205 sp .numBins = bins
168- var cCoef = 100.0 / float64 (bins + 1 )
169206
170207 // clean the bins
171208 for xB := 0 ; xB < bins ; xB ++ {
172209 sp .bins [xB ].floorFFT = 0
173210 sp .bins [xB ].ceilFFT = 0
174211
175- sp .bins [xB ].eqVal = math . Log2 ( float64 ( xB ) + 2 ) * cCoef
212+ sp .bins [xB ].eqVal = 1.0
176213 }
177214
178215 switch stype {
179216
180217 case SpectrumLog :
181218 sp .distributeLog (bins )
219+
182220 case SpectrumEqual :
183221 sp .distributeEqual (bins )
184222
@@ -197,10 +235,9 @@ func (sp *Spectrum) Recalculate(bins int, stype SpectrumType) int {
197235 return bins
198236}
199237
200- // distributeLog distributes the
201238func (sp * Spectrum ) distributeLog (bins int ) {
202- var lo = (dividers [1 ])
203- var hi = dividers [4 ]
239+ var lo = (Frequencies [1 ])
240+ var hi = Frequencies [4 ]
204241
205242 var cF = math .Log10 (lo / hi ) / ((1 / float64 (bins )) - 1 )
206243
@@ -210,9 +247,12 @@ func (sp *Spectrum) distributeLog(bins int) {
210247 return sp .freqToIdx (vFreq , math .Round )
211248 }
212249
250+ var cCoef = 100.0 / float64 (bins + 1 )
251+
213252 for xB := 0 ; xB <= bins ; xB ++ {
214253
215254 sp .bins [xB ].floorFFT = getBinBase (xB )
255+ sp .bins [xB ].eqVal = math .Log2 (float64 (xB )+ 2 ) * cCoef
216256
217257 if xB > 0 {
218258 if sp .bins [xB - 1 ].floorFFT >= sp .bins [xB ].floorFFT {
@@ -225,8 +265,8 @@ func (sp *Spectrum) distributeLog(bins int) {
225265}
226266
227267func (sp * Spectrum ) distributeEqual (bins int ) {
228- var loF = dividers [0 ]
229- var hiF = math .Min (dividers [4 ], sp .sampleRate / 2 )
268+ var loF = Frequencies [0 ]
269+ var hiF = math .Min (Frequencies [4 ], sp .sampleRate / 2 )
230270 var minIdx = sp .freqToIdx (loF , math .Floor )
231271 var maxIdx = sp .freqToIdx (hiF , math .Round )
232272
@@ -265,7 +305,9 @@ func (sp *Spectrum) idxToFreq(bin int) float64 {
265305 return float64 (bin ) * sp .sampleRate / float64 (sp .sampleSize )
266306}
267307
268- func (sp * Spectrum ) freqToIdx (freq float64 , round func (float64 ) float64 ) int {
308+ type mathFunc func (float64 ) float64
309+
310+ func (sp * Spectrum ) freqToIdx (freq float64 , round mathFunc ) int {
269311 var bin = int (round (freq / (sp .sampleRate / float64 (sp .sampleSize ))))
270312
271313 if bin < sp .fftSize {
@@ -275,29 +317,13 @@ func (sp *Spectrum) freqToIdx(freq float64, round func(float64) float64) int {
275317 return sp .fftSize - 1
276318}
277319
278- // AddStream adds an input buffer to the spectrum
279- func (sp * Spectrum ) AddStream (input []float64 ) bool {
280- var s = & stream {
281- input : input ,
282- buf : make ([]float64 , sp .sampleSize ),
283- pBuf : make ([]float64 , sp .sampleSize ),
284- plan : fft .NewPlan (input , sp .fftBuf ),
285- }
286-
287- sp .streamBufs = append (sp .streamBufs , s .buf )
288- sp .streams = append (sp .streams , s )
289- sp .numStreams ++
290-
291- return true
292- }
293-
294- // SetGamma sets the gamma used for distribution spread
295- func (sp * Spectrum ) SetGamma (g float64 ) {
320+ // SetWinVar sets the winVar used for distribution spread
321+ func (sp * Spectrum ) SetWinVar (g float64 ) {
296322 if g <= 0.0 {
297323 g = 1
298324 }
299325
300- sp .gamma = g
326+ sp .winVar = g
301327}
302328
303329// SetSmoothing sets the smoothing parameters
@@ -306,20 +332,5 @@ func (sp *Spectrum) SetSmoothing(factor float64) {
306332 factor = math .SmallestNonzeroFloat64
307333 }
308334
309- sp .smoothFact = factor
310- }
311-
312- // Buffers returns our bin buffers
313- func (sp * Spectrum ) Buffers () [][]float64 {
314- return sp .streamBufs
315- }
316-
317- // StreamCount returns the number of streams in our buffers
318- func (sp * Spectrum ) StreamCount () int {
319- return sp .numStreams
320- }
321-
322- // BinCount returns the number of bins each stream has
323- func (sp * Spectrum ) BinCount () int {
324- return sp .numBins
335+ sp .smoothFactor = factor
325336}
0 commit comments