I made a more final version, and it goes blazing fast, I don't have the time to see the pure FFT transfrom happen on a PDA, definately way less than a second !
The time to first open my recorded, one second wave-file from disk, checking if it's the right format, putting the last 4096 (mono) bytes of it into an array, etc.. cost me another 3 seconds. But that's OK. 4 seconds total calculation time is great !
On the other hand (just some wishful thinking now), this makes me wonder:
if I could capture the wave-bytes directly from memory while they are being received/recorded, then it would be possible to make a real-time tachometer of a continuous sound. Let's say with one indication of the RPM per second or so. But i guess the recorder.dll doesn't allow me to capture parts of this stream of bytes directly.
Agraham, while we're discussing this, would you mind if I would mention you in the credit list of my app ? You sure deserved it !
In fact, you can see the start of it here, and even download a copy: http://users.telenet.be/heliport/
Don't expect too much, I'm just a hobbyist.
@agraham, really amazing and fast, the algorithm and your reaction time, as usual.
@redbird
As agraham was quicker than I, I stopped testing your FFT algorithm.
But I played with agraham's library.
As your samples are real, you dont even need to add the imaginary samples with 0 values.
I entered 4096 real samples in the data() array without adding imaginary samples. You get 2048 real and 2048 imaginary samples in response from the Fft.Transform.
As I didn't know the expected results with your raw data I added the calculation of 2 sine signals, one with one pure sine (first spectral line) and a second one with 3 pure sines (1st, 4th and 10th spectral lines).
would you mind if I would mention you in the credit list of my app ?
Please do. Unfortunately I don't know of any way to get sound samples directly into memory.
@Klaus
Quote:
As your samples are real, you dont even need to add the imaginary samples with 0 values.
I'm not too hot on maths. I understand interpreting the real and imaginary values obtained using the complex FFT with only real input values and the imaginary input values all 0. I don't understand what the real and imaginary values obtained represent when the imaginary input values are also sampled values. I've Googled but not found an answer (that I understand!). Is there an easy explanation?
Also I modified CalcSin with "For i=0 To NM1 Step 2" to only produce real values assuming that the real values of data() are even indeces and imaginary are odd. The expected frequencies seem to appear in the imaginary data and phase in the real data. Would you expect it to be this way round?
EDIT:- I've got the answer to my second question. From (years ago!) brief exposure to FFTs I was under the misapprehension that the output was freqency amplitudes and phase. In fact it is Sine (imaginary) and Cosine (real) frequency amplitudes. I still don't understand the first question!
__________________
Sorry, but I don't answer questions by PM or email.
Please post your queries in the forum.
[quote=klaus;32755As your samples are real, you dont even need to add the imaginary samples with 0 values.
I entered 4096 real samples in the data() array without adding imaginary samples. You get 2048 real and 2048 imaginary samples in response from the Fft.Transform. [/QUOTE]
I tested this with another version, and you are absolutely right:
An fft transform of a 4096 byte array with all real values gives indeed the 2048 real and 2048 imaginary numbers as a result, containing all necessary information.
An fft transform of what I did first, that's a 8192 real+imag byte array, with a real sample and a zero, a real sample and a zero, and so on, gives off course the double number of results, but the last half is completely symmetric, and therefore useless to anyone. That's the way MS Excel does it, and I should have known:
Anyway, my arrays are only half as large now, probably giving even more speed improvement, and especially less memory usage. Thanks for the tip !
In that case for N real samples the DFT returns N/2 real values and N/2 imaginary conjugated values.
I tried also with 0's on the odd indexes for the imaginary part, but I didn't get consistent results.
Could you post your test program with the imaginary input, so I will check if I made a somewhere a mistake or if the results are also not consistent.
When you calculate the FFT in my test program with 3 Sines, you will see that the spectral lines 1,4 and 10 have a value near 1024 for both the real and imaginary value corresponding to the 'frequencies' of the 3 sines. All other values are near 0, as it must be because the sines are pure, only one spectral line per sine. A pure sine means in that case beginning with 0 and with a whole number of periods in the 'window'.
Normally FFT's ampltudes are normalized, when you click onto the A button to calculate the Amplitude of the sine you will see values near 0.707 for the 3 spectral lines (that's the standard normalization in FFT analysers, power spectrum). I have used FFT in the past in one of my programs and normalized the amplitude to get the same amplitude as the original sines wich in the test program is 1.
I had also looked at a Fourier series instead of FFT but it is awfully slow.
The advantage, for redbird, would have been that the bandwidth could probably have been limited to the interesting area.
I suppose that your algorithm is a real input DFT.
I'm not sure what you mean by "your algorithm" but the library does a complex input FFT. I think the long words and funny symbols in the articles that I Google are the problem to my not understanding.
If I set the imaginary part of the input to 0 and make a Cosine input by altering your Sub CalcSin as follows I get what I expect. A Real (Cosine) as a fourth harmonic and two Imaginary (Sine) harmonics as the fundamental and the tenth. I sort of understand this but don't know what the negative signs of the Imaginary values mean or why the Imaginary conjugates are of opposite sign whereas the Real conjugates aren't, something to do with "i" presumably.
Code:
Sub CalcSin(nb) Dim I As Number Dim j As Number, w0 As Number, w1 As Number, w2 As Number
w0=cPI/ND2 w1=cPI/ND2*4 w2=cPI/ND2*10
lbxResult.Clear For i=0To NM1<font color="red"> Step2</font> data(i)=Sin(w0*i) <font color="Red">data(i+1) = 0</font> If nb=3Then data(i)=data(i)+<font color="Red">Cos</font>(w1*i) data(i)=data(i)+Sin(w2*i) EndIf lbxResult.Add(i&""&data(i)) Next FillList(NM1,"Sinus") End Sub
With your original Sub, which inputs samples in both Real and Imaginary input parts the FFT produces aproximate values of
Real at 1 of 1024, 4 of 1 of 1018, 10 of 1024
and at 2047(1) of, 1025, 2044(4) of 1024, 2038(10) of 1040
Imag at 1 of -1022, 4 of 1024, 10 of -1008
and at 2047(1) of, 1025, 2044(4) of 1024, 2038(10) of 1040
What I don't understand is what these represent. Presumably they are amplitudes and obviously they are at the input frequencies but the signs of the values puzzle me. It looks like the initial values in the Imaginary output carry phase information but the relected values of the Imaginary don't, presumably its' something to with "i" again
__________________
Sorry, but I don't answer questions by PM or email.
Please post your queries in the forum.
I looked more deeply into the FFT and played more with your library.
I must apologise I did some mistakes and misinterpreted some results.
Your library works perfectly, sorry for having made you loosing your time.
The imaginary samples set to 0 are necessary.
Setting the data() array with a set of real samples as in my previous test program is almost similar to setting the imaginary samples equal to the real samples and the results looked almost OK.
Attached a new test program allowing to 'play' with your library, with some graphics making hopefully the subject better understandable (desktop only). The program is written with version 6.9. Source code and an exe file for those who don't have version 6.9.
Ahh, thanks Klaus - no wonder I didn't understand what was going on!
I've added a few methods to the library that might speed things up slightly, especially on a device
CopyArray(array As Double) As Double
fast .NET method for cloning of an array
ToAmplitude(real As Double(), imag As Double(), scale As Double) as Double()
where scale determines the scaling of the output values which with a scale value of 1 are the input values
ToPhase(real As Double(), imag As Double()) as Double()
and
ToReal(amplitude As Double(), phase As Double(), scale As Double) as Double()
ToImaginary(amplitude As Double(), phase As Double(), scale As Double) as Double()
where scale is the same value as used for ToAmplitude.
Any comments?
__________________
Sorry, but I don't answer questions by PM or email.
Please post your queries in the forum.
I was about asking for a method to get at least the amplitude because in frequency analysis that's what the user is the most intersted in, the phase is not that impotant. In practice I'v never used Real and Imaginary.
Best regards and thank's.
EDIT:
Have you already uploaded the new version ?
I was thinking about getting Amplitude and Phase directly in return from Fft.Transform as this is the most useful, but there would be the scale variable needed. This would avoid needing to calculate it afterwords.
I have seen that Fft, the name of the FFT object, is highlighted in green in the IDE, is this a new feature ?
Could be intersting for other objects too.
the amplitude because in frequency analysis that's what the user is the most intersted in, the phase is not that impotant.
I kept the conversion as individual ones for that reason so as to keep things quick.
Quote:
I was thinking about getting Amplitude and Phase directly in return from Fft.Transform ... This would avoid needing to calculate it afterwords.
It needs to be calculated separately anyway as the algorithm produces Sine and Cosine. As the overhead of doing them in the Basic4ppc code rather than automatically in the library is very small, only that of a single call to the library and as only Amplitude is interesting a lot of the time I didn't incoporate it into the actual Transform. Also having Real and Imaginary available lets you see what is going on if you need to.
Quote:
I have seen that Fft, the name of the FFT object, is highlighted in green in the IDE
I've no idea why the IDE thinks that FFT is a keyword, it doesn't highlight other library objects, although I have suggested to Erel that it should but he wasn't keen on the idea.
Here's the next version of the library with the five methods above added.
__________________
Sorry, but I don't answer questions by PM or email.
Please post your queries in the forum.