1+ // Package dsp provides audio analysis
2+ //
3+ // Some notes:
4+ //
5+ // https://dlbeer.co.nz/articles/fftvis.html
6+ // https://www.cg.tuwien.ac.at/courses/WissArbeiten/WS2010/processing.pdf
7+ // https://github.com/hvianna/audioMotion-analyzer/blob/master/src/audioMotion-analyzer.js#L1053
8+ // https://dsp.stackexchange.com/questions/6499/help-calculating-understanding-the-mfccs-mel-frequency-cepstrum-coefficients
9+ // https://stackoverflow.com/questions/3694918/how-to-extract-frequency-associated-with-fft-values-in-python
10+ // - https://stackoverflow.com/a/27191172
11+ //
112package dsp
213
314import (
@@ -25,11 +36,12 @@ type Spectrum struct {
2536 numBins int // number of bins we look at
2637 fftSize int // number of fft bins
2738 sampleSize int // number of samples per slice
39+ sType SpectrumType // the type of spectrum distribution
2840 sampleRate float64 // audio sample rate
2941 winVar float64 // window variable
3042 smoothFactor float64 // smothing factor
31- bins []bin // bins for processing
3243 fftBuf []complex128 // fft return buffer
44+ bins []bin // bins for processing
3345 streams []* stream // streams of data
3446}
3547
@@ -50,29 +62,20 @@ type stream struct {
5062// Frequencies are the dividing frequencies
5163var Frequencies = []float64 {
5264 // sub sub bass
53- 20.0 ,
65+ 20.0 , // 0
5466 // sub bass
55- 60.0 ,
67+ 60.0 , // 1
5668 // bass
57- 250.0 ,
69+ 250.0 , // 2
5870 // midrange
59- 4000.0 ,
71+ 4000.0 , // 3
6072 // treble
61- 12000.0 ,
73+ 12000.0 , // 4
6274 // brilliance
63- 22050.0 ,
75+ 22050.0 , // 5
6476 // everything else
6577}
6678
67- // Some notes:
68- //
69- // https://stackoverflow.com/questions/3694918/how-to-extract-frequency-associated-with-fft-values-in-python
70- // - https://stackoverflow.com/a/27191172
71- // https://dlbeer.co.nz/articles/fftvis.html
72- // https://github.com/hvianna/audioMotion-analyzer/blob/master/src/audioMotion-analyzer.js#L1053
73- // https://www.cg.tuwien.ac.at/courses/WissArbeiten/WS2010/processing.pdf
74- // https://dsp.stackexchange.com/questions/6499/help-calculating-understanding-the-mfccs-mel-frequency-cepstrum-coefficients
75-
7679// NewSpectrum will set up our spectrum
7780func NewSpectrum (hz float64 , size int ) * Spectrum {
7881
@@ -84,8 +87,8 @@ func NewSpectrum(hz float64, size int) *Spectrum {
8487 sampleRate : hz ,
8588 smoothFactor : 0.1969 ,
8689 winVar : 1.0 ,
87- bins : make ([]bin , size + 1 ),
8890 fftBuf : make ([]complex128 , fftSize ),
91+ bins : make ([]bin , size + 1 ),
8992 streams : make ([]* stream , 0 , 2 ),
9093 }
9194
@@ -169,7 +172,7 @@ func (sp *Spectrum) Process(win window.Function) {
169172
170173 mag = math .Pow (mag , pow )
171174
172- // Smoothing
175+ // time smoothing
173176
174177 mag *= (1.0 - sf )
175178 mag += stream .pBuf [xB ] * sf
@@ -185,7 +188,7 @@ func (sp *Spectrum) Process(win window.Function) {
185188}
186189
187190// Recalculate rebuilds our frequency bins
188- func (sp * Spectrum ) Recalculate (bins int , stype SpectrumType ) int {
191+ func (sp * Spectrum ) Recalculate (bins int ) int {
189192
190193 switch {
191194 case bins >= sp .fftSize :
@@ -204,7 +207,7 @@ func (sp *Spectrum) Recalculate(bins int, stype SpectrumType) int {
204207 sp .bins [xB ].eqVal = 1.0
205208 }
206209
207- switch stype {
210+ switch sp . sType {
208211
209212 case SpectrumLog :
210213 sp .distributeLog (bins )
@@ -215,6 +218,7 @@ func (sp *Spectrum) Recalculate(bins int, stype SpectrumType) int {
215218 default :
216219 }
217220
221+ // set widths
218222 for xB := 0 ; xB < bins ; xB ++ {
219223 if sp .bins [xB ].ceilFFT == sp .bins [xB ].floorFFT {
220224 sp .bins [xB ].widthFFT = 1
@@ -227,6 +231,9 @@ func (sp *Spectrum) Recalculate(bins int, stype SpectrumType) int {
227231 return bins
228232}
229233
234+ // distributeLog does not *actually* distribute logarithmically
235+ // it is a best guess naive attempt right now.
236+ // i will continue work on it - winter
230237func (sp * Spectrum ) distributeLog (bins int ) {
231238 var lo = (Frequencies [1 ])
232239 var hi = Frequencies [4 ]
@@ -241,7 +248,9 @@ func (sp *Spectrum) distributeLog(bins int) {
241248
242249 var cCoef = 100.0 / float64 (bins + 1 )
243250
244- for xB := 0 ; xB <= bins ; xB ++ {
251+ sp .bins [0 ].floorFFT = lo &
252+
253+ for xB := 0 ; xB < bins ; xB ++ {
245254
246255 sp .bins [xB ].floorFFT = getBinBase (xB )
247256 sp .bins [xB ].eqVal = math .Log2 (float64 (xB )+ 2 ) * cCoef
@@ -309,6 +318,11 @@ func (sp *Spectrum) freqToIdx(freq float64, round mathFunc) int {
309318 return sp .fftSize - 1
310319}
311320
321+ // SetType will set the spectrum type
322+ func (sp * Spectrum ) SetType (st SpectrumType ) {
323+ sp .sType = st
324+ }
325+
312326// SetWinVar sets the winVar used for distribution spread
313327func (sp * Spectrum ) SetWinVar (g float64 ) {
314328 switch {
0 commit comments