ddf.minim.analysis
Class FourierTransform

java.lang.Object
  extended by ddf.minim.analysis.FourierTransform
Direct Known Subclasses:
DFT, FFT

public abstract class FourierTransform
extends java.lang.Object

A Fourier Transform is an algorithm that transforms a signal in the time domain, such as a sample buffer, into a signal in the frequency domain, often called the spectrum. The spectrum does not represent individual frequencies, but actually represents frequency bands centered on particular frequencies. The center frequency of each band is usually expressed as a fraction of the sampling rate of the time domain signal and is equal to the index of the frequency band divided by the total number of bands. The total number of frequency bands is usually equal to the length of the time domain signal, but access is only provided to frequency bands with indices less than half the length, because they correspond to frequencies below the Nyquist frequency. In other words, given a signal of length N, there will be N/2 frequency bands in the spectrum.

As an example, if you construct a FourierTransform with a timeSize of 1024 and and a sampleRate of 44100 Hz, then the spectrum will contain values for frequencies below 22010 Hz, which is the Nyquist frequency (half the sample rate). If you ask for the value of band number 5, this will correspond to a frequency band centered on 5/1024 * 44100 = 0.0048828125 * 44100 = 215 Hz. The width of that frequency band is equal to 2/1024, expressed as a fraction of the total bandwidth of the spectrum. The total bandwith of the spectrum is equal to the Nyquist frequency, which in this case is 22050, so the bandwidth is equal to about 50 Hz. It is not necessary for you to remember all of these relationships, though it is good to be aware of them. The function getFreq() allows you to query the spectrum with a frequency in Hz and the function getBandWidth() will return the bandwidth in Hz of each frequency band in the spectrum.

Usage

A typical usage of a FourierTransform is to analyze a signal so that the frequency spectrum may be represented in some way, typically with vertical lines. You could do this in Processing with the following code, where audio is an AudioSource and fft is an FFT (one of the derived classes of FourierTransform).

 fft.forward(audio.left);
 for (int i = 0; i < fft.specSize(); i++)
 {
   // draw the line for frequency band i, scaling it by 4 so we can see it a bit better
   line(i, height, i, height - fft.getBand(i) * 4);
 }
 
Windowing

Windowing is the process of shaping the audio samples before transforming them to the frequency domain. The Fourier Transform assumes the sample buffer is is a repetitive signal, if a sample buffer is not truly periodic within the measured interval sharp discontinuities may arise that can introduce spectral leakage. Spectral leakage is the speading of signal energy across multiple FFT bins. This "spreading" can drown out narrow band signals and hinder detection.

A windowing function attempts to reduce spectral leakage by attenuating the measured sample buffer at its end points to eliminate discontinuities. If you call the window() function with an appropriate WindowFunction, such as HammingWindow(), the sample buffers passed to the object for analysis will be shaped by the current window before being transformed. The result of using a window is to reduce the leakage in the spectrum somewhat.

Averages

FourierTransform also has functions that allow you to request the creation of an average spectrum. An average spectrum is simply a spectrum with fewer bands than the full spectrum where each average band is the average of the amplitudes of some number of contiguous frequency bands in the full spectrum.

linAverages() allows you to specify the number of averages that you want and will group frequency bands into groups of equal number. So if you have a spectrum with 512 frequency bands and you ask for 64 averages, each average will span 8 bands of the full spectrum.

logAverages() will group frequency bands by octave and allows you to specify the size of the smallest octave to use (in Hz) and also how many bands to split each octave into. So you might ask for the smallest octave to be 60 Hz and to split each octave into two bands. The result is that the bandwidth of each average is different. One frequency is an octave above another when it's frequency is twice that of the lower frequency. So, 120 Hz is an octave above 60 Hz, 240 Hz is an octave above 120 Hz, and so on. When octaves are split, they are split based on Hz, so if you split the octave 60-120 Hz in half, you will get 60-90Hz and 90-120Hz. You can see how these bandwidths increase as your octave sizes grow. For instance, the last octave will always span sampleRate/4 - sampleRate/2, which in the case of audio sampled at 44100 Hz is 11025-22010 Hz. These logarithmically spaced averages are usually much more useful than the full spectrum or the linearly spaced averages because they map more directly to how humans perceive sound.

calcAvg() allows you to specify the frequency band you want an average calculated for. You might ask for 60-500Hz and this function will group together the bands from the full spectrum that fall into that range and average their amplitudes for you.

If you don't want any averages calculated, then you can call noAverages(). This will not impact your ability to use calcAvg(), it will merely prevent the object from calculating an average array every time you use forward().

Inverse Transform

FourierTransform also supports taking the inverse transform of a spectrum. This means that a frequency spectrum will be transformed into a time domain signal and placed in a provided sample buffer. The length of the time domain signal will be timeSize() long. The set and scale functions allow you the ability to shape the spectrum already stored in the object before taking the inverse transform. You might use these to filter frequencies in a spectrum or modify it in some other way.

Author:
Damien Di Fede
See Also:
The Discrete Fourier Transform

Field Summary
protected  float[] averages
           
protected  int avgPerOctave
           
protected  float bandWidth
           
static WindowFunction BARTLETT
          A constant indicating a Bartlett window should be used on sample buffers.
static WindowFunction BARTLETTHANN
          A constant indicating a Bartlett-Hann window should be used on sample buffers.
static WindowFunction COSINE
          A constant indicating a Cosine window should be used on sample buffers.
static WindowFunction HAMMING
          A constant indicating a Hamming window should be used on sample buffers.
static WindowFunction HANN
          A constant indicating a Hann window should be used on sample buffers.
protected  float[] imag
           
static WindowFunction LANCZOS
          A constant indicating a Lanczos window should be used on sample buffers.
protected static int LINAVG
           
protected static int LOGAVG
           
protected static int NOAVG
           
static WindowFunction NONE
          A constant indicating no window should be used on sample buffers.
protected  int octaves
           
protected  float[] real
           
protected  int sampleRate
           
protected  float[] spectrum
           
protected  int timeSize
           
static WindowFunction TRIANGULAR
          A constant indicating a Triangular window should be used on sample buffers.
protected static float TWO_PI
           
protected  int whichAverage
           
protected  WindowFunction windowFunction
           
 
Method Summary
protected abstract  void allocateArrays()
           
 int avgSize()
          Returns the number of averages currently being calculated.
 float calcAvg(float lowFreq, float hiFreq)
          Calculate the average amplitude of the frequency band bounded by lowFreq and hiFreq, inclusive.
protected  void doWindow(float[] samples)
           
protected  void fillSpectrum()
           
 void forward(AudioBuffer buffer)
          Performs a forward transform on buffer.
 void forward(AudioBuffer buffer, int startAt)
          Performs a forward transform on buffer.
abstract  void forward(float[] buffer)
          Performs a forward transform on buffer.
 void forward(float[] buffer, int startAt)
          Performs a forward transform on values in buffer.
 int freqToIndex(float freq)
          Returns the index of the frequency band that contains the requested frequency.
 float getAverageCenterFrequency(int i)
          Returns the center frequency of the ith average band.
 float getAvg(int i)
          Gets the value of the ith average.
 float getBand(int i)
          Returns the amplitude of the requested frequency band.
 float getBandWidth()
          Returns the width of each frequency band in the spectrum (in Hz).
 float getFreq(float freq)
          Gets the amplitude of the requested frequency in the spectrum.
 float indexToFreq(int i)
          Returns the middle frequency of the ith band.
 void inverse(AudioBuffer buffer)
          Performs an inverse transform of the frequency spectrum and places the result in buffer.
abstract  void inverse(float[] buffer)
          Performs an inverse transform of the frequency spectrum and places the result in buffer.
 void inverse(float[] freqReal, float[] freqImag, float[] buffer)
          Performs an inverse transform of the frequency spectrum represented by freqReal and freqImag and places the result in buffer.
 void linAverages(int numAvg)
          Sets the number of averages used when computing the spectrum and spaces the averages in a linear manner.
 void logAverages(int minBandwidth, int bandsPerOctave)
          Sets the number of averages used when computing the spectrum based on the minimum bandwidth for an octave and the number of bands per octave.
 void noAverages()
          Sets the object to not compute averages.
abstract  void scaleBand(int i, float s)
          Scales the amplitude of the ith frequency band by s.
 void scaleFreq(float freq, float s)
          Scales the amplitude of the requested frequency by a.
abstract  void setBand(int i, float a)
          Sets the amplitude of the ith frequency band to a.
protected  void setComplex(float[] r, float[] i)
           
 void setFreq(float freq, float a)
          Sets the amplitude of the requested frequency in the spectrum to a.
 int specSize()
          Returns the size of the spectrum created by this transform.
 int timeSize()
          Returns the length of the time domain signal expected by this transform.
 void window(WindowFunction windowFunction)
          Sets the window to use on the samples before taking the forward transform.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

LINAVG

protected static final int LINAVG
See Also:
Constant Field Values

LOGAVG

protected static final int LOGAVG
See Also:
Constant Field Values

NOAVG

protected static final int NOAVG
See Also:
Constant Field Values

NONE

public static final WindowFunction NONE
A constant indicating no window should be used on sample buffers. Also referred as a Rectangular window.


HAMMING

public static final WindowFunction HAMMING
A constant indicating a Hamming window should be used on sample buffers.


HANN

public static final WindowFunction HANN
A constant indicating a Hann window should be used on sample buffers.


COSINE

public static final WindowFunction COSINE
A constant indicating a Cosine window should be used on sample buffers.


TRIANGULAR

public static final WindowFunction TRIANGULAR
A constant indicating a Triangular window should be used on sample buffers.


BARTLETT

public static final WindowFunction BARTLETT
A constant indicating a Bartlett window should be used on sample buffers.


BARTLETTHANN

public static final WindowFunction BARTLETTHANN
A constant indicating a Bartlett-Hann window should be used on sample buffers.


LANCZOS

public static final WindowFunction LANCZOS
A constant indicating a Lanczos window should be used on sample buffers.


TWO_PI

protected static final float TWO_PI
See Also:
Constant Field Values

timeSize

protected int timeSize

sampleRate

protected int sampleRate

bandWidth

protected float bandWidth

windowFunction

protected WindowFunction windowFunction

real

protected float[] real

imag

protected float[] imag

spectrum

protected float[] spectrum

averages

protected float[] averages

whichAverage

protected int whichAverage

octaves

protected int octaves

avgPerOctave

protected int avgPerOctave
Method Detail

allocateArrays

protected abstract void allocateArrays()

setComplex

protected void setComplex(float[] r,
                          float[] i)

fillSpectrum

protected void fillSpectrum()

noAverages

public void noAverages()
Sets the object to not compute averages.


linAverages

public void linAverages(int numAvg)
Sets the number of averages used when computing the spectrum and spaces the averages in a linear manner. In other words, each average band will be specSize() / numAvg bands wide.

Parameters:
numAvg - how many averages to compute

logAverages

public void logAverages(int minBandwidth,
                        int bandsPerOctave)
Sets the number of averages used when computing the spectrum based on the minimum bandwidth for an octave and the number of bands per octave. For example, with audio that has a sample rate of 44100 Hz, logAverages(11, 1) will result in 12 averages, each corresponding to an octave, the first spanning 0 to 11 Hz. To ensure that each octave band is a full octave, the number of octaves is computed by dividing the Nyquist frequency by two, and then the result of that by two, and so on. This means that the actual bandwidth of the lowest octave may not be exactly the value specified.

Parameters:
minBandwidth - the minimum bandwidth used for an octave
bandsPerOctave - how many bands to split each octave into

window

public void window(WindowFunction windowFunction)
Sets the window to use on the samples before taking the forward transform. If an invalid window is asked for, an error will be reported and the current window will not be changed.

Parameters:
windowFunction -

doWindow

protected void doWindow(float[] samples)

timeSize

public int timeSize()
Returns the length of the time domain signal expected by this transform.

Returns:
the length of the time domain signal expected by this transform

specSize

public int specSize()
Returns the size of the spectrum created by this transform. In other words, the number of frequency bands produced by this transform. This is typically equal to timeSize()/2 + 1, see above for an explanation.

Returns:
the size of the spectrum

getBand

public float getBand(int i)
Returns the amplitude of the requested frequency band.

Parameters:
i - the index of a frequency band
Returns:
the amplitude of the requested frequency band

getBandWidth

public float getBandWidth()
Returns the width of each frequency band in the spectrum (in Hz). It should be noted that the bandwidth of the first and last frequency bands is half as large as the value returned by this function.

Returns:
the width of each frequency band in Hz.

setBand

public abstract void setBand(int i,
                             float a)
Sets the amplitude of the ith frequency band to a. You can use this to shape the spectrum before using inverse().

Parameters:
i - the frequency band to modify
a - the new amplitude

scaleBand

public abstract void scaleBand(int i,
                               float s)
Scales the amplitude of the ith frequency band by s. You can use this to shape the spectrum before using inverse().

Parameters:
i - the frequency band to modify
s - the scaling factor

freqToIndex

public int freqToIndex(float freq)
Returns the index of the frequency band that contains the requested frequency.

Parameters:
freq - the frequency you want the index for (in Hz)
Returns:
the index of the frequency band that contains freq

indexToFreq

public float indexToFreq(int i)
Returns the middle frequency of the ith band.

Parameters:
i - the index of the band you want to middle frequency of

getAverageCenterFrequency

public float getAverageCenterFrequency(int i)
Returns the center frequency of the ith average band.

Parameters:
i - which average band you want the center frequency of.

getFreq

public float getFreq(float freq)
Gets the amplitude of the requested frequency in the spectrum.

Parameters:
freq - the frequency in Hz
Returns:
the amplitude of the frequency in the spectrum

setFreq

public void setFreq(float freq,
                    float a)
Sets the amplitude of the requested frequency in the spectrum to a.

Parameters:
freq - the frequency in Hz
a - the new amplitude

scaleFreq

public void scaleFreq(float freq,
                      float s)
Scales the amplitude of the requested frequency by a.

Parameters:
freq - the frequency in Hz
s - the scaling factor

avgSize

public int avgSize()
Returns the number of averages currently being calculated.

Returns:
the length of the averages array

getAvg

public float getAvg(int i)
Gets the value of the ith average.

Parameters:
i - the average you want the value of
Returns:
the value of the requested average band

calcAvg

public float calcAvg(float lowFreq,
                     float hiFreq)
Calculate the average amplitude of the frequency band bounded by lowFreq and hiFreq, inclusive.

Parameters:
lowFreq - the lower bound of the band
hiFreq - the upper bound of the band
Returns:
the average of all spectrum values within the bounds

forward

public abstract void forward(float[] buffer)
Performs a forward transform on buffer.

Parameters:
buffer - the buffer to analyze

forward

public void forward(float[] buffer,
                    int startAt)
Performs a forward transform on values in buffer.

Parameters:
buffer - the buffer of samples
startAt - the index to start at in the buffer. there must be at least timeSize() samples between the starting index and the end of the buffer. If there aren't, an error will be issued and the operation will not be performed.

forward

public void forward(AudioBuffer buffer)
Performs a forward transform on buffer.

Parameters:
buffer - the buffer to analyze

forward

public void forward(AudioBuffer buffer,
                    int startAt)
Performs a forward transform on buffer.

Parameters:
buffer - the buffer of samples
startAt - the index to start at in the buffer. there must be at least timeSize() samples between the starting index and the end of the buffer.

inverse

public abstract void inverse(float[] buffer)
Performs an inverse transform of the frequency spectrum and places the result in buffer.

Parameters:
buffer - the buffer to place the result of the inverse transform in

inverse

public void inverse(AudioBuffer buffer)
Performs an inverse transform of the frequency spectrum and places the result in buffer.

Parameters:
buffer - the buffer to place the result of the inverse transform in

inverse

public void inverse(float[] freqReal,
                    float[] freqImag,
                    float[] buffer)
Performs an inverse transform of the frequency spectrum represented by freqReal and freqImag and places the result in buffer.

Parameters:
freqReal - the real part of the frequency spectrum
freqImag - the imaginary part the frequency spectrum
buffer - the buffer to place the inverse transform in