However, when implemented and compared with other FFT objects (which I'm doing in max/msp) the results of the above algorithm don't seem to match at all.
Would anyone be able to tell me if there is an issue with the algorithm or implementation? If nothing is wrong with the algorithm then there must be an issue with how I am sending the values or something...
Some points to consider:
1. I am performing the FFT on audio samples which are 1D instead of an image. The input I'm sending it is a window of 1024 audio samples, (ie vec4(sample,0,0,0) ) the dimensions are 1024x1.
2. I don't really understand the Subtransform size and it's hard to find clear info about it from google searching, so I am not sure if I'm setting it correctly.
3. I set the transform size as the FFT size, is that correct?
Here is the algorithm implemented in my shader:
Code: Select all
const float TWO_PI_NEG = -6.2831853072;
varying vec2 texcoord0;
uniform sampler2D tex0;
uniform float fftSize = 1024;
uniform float subtransformSize = 4;
uniform float subtransformSizeHalf = 2;
uniform float horizontal = 1;
float fftSizeHalf = fftSize * 0.5;
//
vec2 multiplyComplex (vec2 a, vec2 b) {
return vec2(a[0] * b[0] - a[1] * b[1], a[1] * b[0] + a[0] * b[1]);
}
//GPU FFT using a Stockham formulation
vec4 fft (
sampler2D src,
vec2 coord,
float transformSize,
float transformSizeHalf,
float subtransformSize,
float subtransformSizeHalf,
float horizontal
) {
float index;
if (horizontal == 1) {
index = coord.x * transformSize - 0.5;
} else {
index = coord.y * transformSize - 0.5;
}
float evenIndex = floor(index / subtransformSize) * subtransformSizeHalf + mod(index, subtransformSizeHalf);
//transform two complex sequences simultaneously
vec4 even;
vec4 odd;
if (horizontal == 1) {
even = texture2D(src, vec2(evenIndex + 0.5, gl_FragCoord.y) / transformSize).rgba;
odd = texture2D(src, vec2(evenIndex + transformSizeHalf + 0.5, gl_FragCoord.y) / transformSize).rgba;
} else {
even = texture2D(src, vec2(gl_FragCoord.x, evenIndex + 0.5) / transformSize).rgba;
odd = texture2D(src, vec2(gl_FragCoord.x, evenIndex + transformSizeHalf + 0.5) / transformSize).rgba;
}
float twiddleArgument1D = TWO_PI_NEG * (index / subtransformSize);
vec2 twiddle1D = vec2(cos(twiddleArgument1D), sin(twiddleArgument1D));
vec2 outputA = even.xy + multiplyComplex(twiddle1D, odd.xy); //even.xy
vec2 outputB = even.zw + multiplyComplex(twiddle1D, odd.zw); //even.zw
return vec4(outputA, outputB);
}
//
void main(void){
gl_FragColor = fft(tex0, texcoord0, fftSize, fftSizeHalf, subtransformSize, subtransformSizeHalf, 1.);
}