org.hermit.dsp
Class FFTTransformer

java.lang.Object
  extended by org.hermit.dsp.FFTTransformer

public final class FFTTransformer
extends java.lang.Object

Implementation of the Cooley–Tukey FFT algorithm by Tsan-Kuang Lee, for real-valued data and results: http://www.ling.upenn.edu/~tklee/Projects/dsp/

His copyright statement: "Do whatever you want with the code. Feedbacks and improvement welcome."

Usage: create an FFTTransformer with a specified block size, to pre-allocate the necessary resources. Then, for each block that you want to transform:

The flow is broken up like this to allow you to make best use of locks. For example, if the input buffer is also accessed by a thread which reads from the audio, you only need to lock out that thread during setInput(float[], int, int), not the entire FFT process.


Constructor Summary
FFTTransformer(int size)
          Create an FFT transformer for a given sample size.
FFTTransformer(int size, Window.Function winfunc)
          Create an FFT transformer for a given sample size.
FFTTransformer(int size, Window window)
          Create an FFT transformer for a given sample size.
 
Method Summary
 int findKeyFrequencies(float[] spectrum, float[] results)
          Given the results of an FFT, identify prominent frequencies in the spectrum.
 float[] getResults(float[] buffer)
          Get the real results of the last transformation.
 int getResults(float[] average, float[][] histories, int index)
          Get the rolling average real results of the last n transformations.
 void setInput(float[] input, int off, int count)
          Set up a new data block for the FFT algorithm.
 void setInput(short[] input, int off, int count)
          Set up a new data block for the FFT algorithm.
 void setWindowFunc(Window.Function func)
          Set a new windowing function for this analyser.
 void transform()
          Transform the data provided in the last call to setInput.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Constructor Detail

FFTTransformer

public FFTTransformer(int size)
Create an FFT transformer for a given sample size. This preallocates resources appropriate to that block size.

Parameters:
size - The number of samples in a block that we will be asked to transform. Must be a power of 2.
Throws:
java.lang.IllegalArgumentException - Invalid parameter.

FFTTransformer

public FFTTransformer(int size,
                      Window.Function winfunc)
Create an FFT transformer for a given sample size. This preallocates resources appropriate to that block size. A specified window function will be applied to all input data.

Parameters:
size - The number of samples in a block that we will be asked to transform. Must be a power of 2.
winfunc - Window function to apply to all input data.
Throws:
java.lang.IllegalArgumentException - Invalid parameter.

FFTTransformer

public FFTTransformer(int size,
                      Window window)
Create an FFT transformer for a given sample size. This preallocates resources appropriate to that block size. A specified window function will be applied to all input data.

Parameters:
size - The number of samples in a block that we will be asked to transform. Must be a power of 2.
window - Window function to apply to all input data. Its block size must be the same as the size parameter.
Throws:
java.lang.IllegalArgumentException - Invalid parameter.
Method Detail

setWindowFunc

public void setWindowFunc(Window.Function func)
Set a new windowing function for this analyser.

Parameters:
func - The desired windowing function.

setInput

public final void setInput(float[] input,
                           int off,
                           int count)
Set up a new data block for the FFT algorithm. The data in the provided buffer will be copied out, and that buffer will not be referenced again. This is separated out from the main computation to allow for more efficient use of locks.

Parameters:
input - The input data buffer.
off - Offset in the buffer at which the data to be transformed starts.
count - Number of samples in the data to be transformed. Must be the same as the size parameter that was given to the constructor.
Throws:
java.lang.IllegalArgumentException - Invalid data size.

setInput

public final void setInput(short[] input,
                           int off,
                           int count)
Set up a new data block for the FFT algorithm. The data in the provided buffer will be copied out, and that buffer will not be referenced again. This is separated out from the main computation to allow for more efficient use of locks.

Parameters:
input - The input data buffer.
off - Offset in the buffer at which the data to be transformed starts.
count - Number of samples in the data to be transformed. Must be the same as the size parameter that was given to the constructor.
Throws:
java.lang.IllegalArgumentException - Invalid data size.

transform

public final void transform()
Transform the data provided in the last call to setInput.


getResults

public final float[] getResults(float[] buffer)
Get the real results of the last transformation.

Parameters:
buffer - Buffer in which the real part of the results will be placed. This buffer must be half the length of the input block. If transform() has not been called, the results will be garbage.
Returns:
The parameter buffer.
Throws:
java.lang.IllegalArgumentException - Invalid buffer size.

getResults

public final int getResults(float[] average,
                            float[][] histories,
                            int index)
Get the rolling average real results of the last n transformations.

Parameters:
average - Buffer in which the averaged real part of the results will be maintained. This buffer must be half the length of the input block. It is important that this buffer is kept intact and undisturbed between calls, as the average calculation for each value depends on the previous average.
histories - Buffer in which the historical values of the results will be kept. This must be a rectangular array, the first dimension being the same as average. The second dimension determines the length of the history, and hence the time over which values are averaged. It is important that this buffer is kept intact and undisturbed between calls.
index - Current history index. The caller needs to pass in zero initially, and save the return value of this method to pass in as index next time.
Returns:
The updated index value. Pass this in as the index parameter next time around.
Throws:
java.lang.IllegalArgumentException - Invalid buffer size.

findKeyFrequencies

public final int findKeyFrequencies(float[] spectrum,
                                    float[] results)
Given the results of an FFT, identify prominent frequencies in the spectrum.

Note: this is experimental and not very good.

Parameters:
spectrum - Audio spectrum data, as returned by getResults(float[]).
results - Buffer into which the results will be placed.
Returns:
The parameter buffer.
Throws:
java.lang.IllegalArgumentException - Invalid buffer size.