In my question yesterday I said that I have a self-written Fourier transform and have to get to the data of the sound card. I have the latter now. I've already answered my question from yesterday. (Self-praise stinks, I know).
I'll show you the relevant code. Can you see where the problem is? I don't understand what's wrong with that.
With my circumstances and settings (sample rate of my sound card, size of the buffer, ...) the result is a double array with a length of 4097 and a queried time (used_milliseconds
) of 43 milliseconds. The variable Time_
is therefore incremented by (usedMilliseconds / DataArray.Length)
, i.e. by 0.010495 milliseconds, while the index for the DataArray
– cnt
– is incremented by 1. I'm sure that's okay.
However, the while loops only run until the cycle time T has passed. So I can guarantee (at least that's the plan) that I "get the figure (360°)" exactly once, if you now know what I mean, in order to find out the x-part of the center of mass.
The goal is to store magnitude of these freqs in the class-wide variables, f.e. x_F_0200
, which is queried by another procedure in order to draw a few bars.
getLatestData()
fills a newly-declared double Array with, as mentioned, 4097 doubles. Got from the soundcard.
The FFT() procedure is run through by a system.threading.thread. So it shouldn't be a speed issue. The procedure that draws runs approximately every 25 milliseconds. FFT()
is finished long ago and doesn't run unnecessarily ;)
The Problem
My problem is that my code is very imprecise. When I turn on a Youtube song like this, the bars look partially accurate (from left (Bass) to the right (treble)), but when I turn on a test tone, you can see that it is not going well. All bars rise, just not the one right one which should. Damned. 😕
Edit 19.12.2021 14:45 Uhr:
For this test tone (500Hz) I get this picture:
For this test tone (700 Hz) I get this picture:
For this test tone (1000Hz) I get this picture:
While a song is playing, it looks reasonably accurate. The rectangles for the bass rise while the beat is coming, with light voices the right rectangles rise. You could almost believe that it is correct. But yes, from the test tones, I know it's still wrong. (I assume that these test tones are correct :D ).
I only use a BufferSize of 1024 bytes, so my DataArray is 513 bytes in size. The usedMilliseconds are 5.3333. So much less than yesterday.
In addition, the while loops run as long as possible in order to use the full 5.333 milliseconds, but not 100%, because I don't want to have the last half / third / eighth of a cycle.
VB.NET 19.12.2021 14:45
Private Sub FFT()
If Not continue_ Then
Return
End If
getLatestData()
If DataArray Is Nothing Then
Return
End If
Dim Time_ As Double ' in ms
''№ 1
'cnt = 0
'x_F_0020 = 0.0F
'Time_ = 0.0
'While cnt < CInt(Math.Floor(usedMilliseconds / (1.0 / 20.0 * 1000.0) * Math.Floor(DataArray.Length / (usedMilliseconds / (1.0 / 20.0 * 1000.0)))))
' x_F_0020 += CSng(DataArray(cnt) * RealPart(20.0, Time_))
' Time_ += (usedMilliseconds / DataArray.Length)
' cnt += 1
' If cnt >= DataArray.Length Then Exit While
'End While
'x_F_0020 /= cnt
'№ 2
cnt = 0
x_F_0040 = 0.0F
Time_ = 0.0
While cnt < CInt(Math.Floor(usedMilliseconds / (1.0 / 40.0 * 1000.0) * Math.Floor(DataArray.Length / (usedMilliseconds / (1.0 / 40.0 * 1000.0)))))
x_F_0040 += CSng(DataArray(cnt) * RealPart(40.0, Time_))
Time_ += (usedMilliseconds / DataArray.Length)
cnt += 1
End While
x_F_0040 /= cnt
'№ 3
cnt = 0
x_F_0060 = 0.0F
Time_ = 0.0
While cnt < CInt(Math.Floor(usedMilliseconds / (1.0 / 60.0 * 1000.0) * Math.Floor(DataArray.Length / (usedMilliseconds / (1.0 / 60.0 * 1000.0)))))
x_F_0060 += CSng(DataArray(cnt) * RealPart(60.0, Time_))
Time_ += (usedMilliseconds / DataArray.Length)
cnt += 1
End While
x_F_0060 /= cnt
'№ 4
cnt = 0
x_F_0100 = 0.0F
Time_ = 0.0
While cnt < CInt(Math.Floor(usedMilliseconds / (1.0 / 100.0 * 1000.0) * Math.Floor(DataArray.Length / (usedMilliseconds / (1.0 / 100.0 * 1000.0)))))
x_F_0100 += CSng(DataArray(cnt) * RealPart(100.0 / 1000.0F, Time_))
Time_ += (usedMilliseconds / DataArray.Length)
cnt += 1
End While
x_F_0100 /= cnt
x_F_0100 /= 5.0F
'№ 5
cnt = 0
x_F_0200 = 0.0F
Time_ = 0.0
While cnt < CInt(Math.Floor(usedMilliseconds / (1.0 / 200.0 * 1000.0) * Math.Floor(DataArray.Length / (usedMilliseconds / (1.0 / 200.0 * 1000.0)))))
x_F_0200 += CSng(DataArray(cnt) * RealPart(200.0 / 1000.0, Time_))
Time_ += (usedMilliseconds / DataArray.Length)
cnt += 1
End While
x_F_0200 /= cnt
x_F_0200 /= 5.0F
'№ 6
cnt = 0
x_F_0300 = 0.0F
Time_ = 0.0
While cnt < CInt(Math.Floor(usedMilliseconds / (1.0 / 300.0 * 1000.0) * Math.Floor(DataArray.Length / (usedMilliseconds / (1.0 / 300.0 * 1000.0)))))
x_F_0300 += CSng(DataArray(cnt) * RealPart(300.0 / 1000.0, Time_))
Time_ += (usedMilliseconds / DataArray.Length)
cnt += 1
End While
x_F_0300 /= cnt
'№ 7
cnt = 0
x_F_0400 = 0.0F
Time_ = 0.0
While cnt < CInt(Math.Floor(usedMilliseconds / (1.0 / 400.0 * 1000.0) * Math.Floor(DataArray.Length / (usedMilliseconds / (1.0 / 400.0 * 1000.0)))))
x_F_0400 += CSng(DataArray(cnt) * RealPart(400.0 / 1000.0, Time_))
Time_ += (usedMilliseconds / DataArray.Length)
cnt += 1
End While
x_F_0400 /= cnt
'№ 8
cnt = 0
x_F_0500 = 0.0F
Time_ = 0.0
While cnt < CInt(Math.Floor(usedMilliseconds / (1.0 / 500.0 * 1000.0) * Math.Floor(DataArray.Length / (usedMilliseconds / (1.0 / 500.0 * 1000.0)))))
x_F_0500 += CSng(DataArray(cnt) * RealPart(500.0 / 1000.0, Time_))
Time_ += (usedMilliseconds / DataArray.Length)
cnt += 1
End While
x_F_0500 /= cnt
'№ 9
cnt = 0
x_F_0600 = 0.0F
Time_ = 0.0
While cnt < CInt(Math.Floor(usedMilliseconds / (1.0 / 600.0 * 1000.0) * Math.Floor(DataArray.Length / (usedMilliseconds / (1.0 / 600.0 * 1000.0)))))
x_F_0600 += CSng(DataArray(cnt) * RealPart(600.0 / 1000.0, Time_))
Time_ += (usedMilliseconds / DataArray.Length)
cnt += 1
End While
x_F_0600 /= cnt
'№ 10
cnt = 0
x_F_0700 = 0.0F
Time_ = 0.0
While cnt < CInt(Math.Floor(usedMilliseconds / (1.0 / 700.0 * 1000.0) * Math.Floor(DataArray.Length / (usedMilliseconds / (1.0 / 700.0 * 1000.0)))))
x_F_0700 += CSng(DataArray(cnt) * RealPart(700.0 / 1000.0, Time_))
Time_ += (usedMilliseconds / DataArray.Length)
cnt += 1
End While
x_F_0700 /= cnt
'№ 11
cnt = 0
x_F_1000 = 0.0F
Time_ = 0.0
While cnt < CInt(Math.Floor(usedMilliseconds / (1.0 / 1000.0 * 1000.0) * Math.Floor(DataArray.Length / (usedMilliseconds / (1.0 / 1000.0 * 1000.0)))))
x_F_1000 += CSng(DataArray(cnt) * RealPart(1000.0 / 1000.0, Time_))
Time_ += (usedMilliseconds / DataArray.Length)
cnt += 1
End While
x_F_1000 /= cnt
'№ 12
cnt = 0
x_F_2000 = 0.0F
Time_ = 0.0
While cnt < CInt(Math.Floor(usedMilliseconds / (1.0 / 2000.0 * 1000.0) * Math.Floor(DataArray.Length / (usedMilliseconds / (1.0 / 2000.0 * 1000.0)))))
x_F_2000 += CSng(DataArray(cnt) * RealPart(2000.0 / 1000.0, Time_))
Time_ += (usedMilliseconds / DataArray.Length)
cnt += 1
End While
x_F_2000 /= cnt
'№ 13
cnt = 0
x_F_3000 = 0.0F
Time_ = 0.0
While cnt < CInt(Math.Floor(usedMilliseconds / (1.0 / 3000.0 * 1000.0) * Math.Floor(DataArray.Length / (usedMilliseconds / (1.0 / 3000.0 * 1000.0)))))
x_F_3000 += CSng(DataArray(cnt) * RealPart(3000.0 / 1000.0, Time_))
Time_ += (usedMilliseconds / DataArray.Length)
cnt += 1
End While
x_F_3000 /= cnt
'№ 14
cnt = 0
x_F_5000 = 0.0F
Time_ = 0.0
While cnt < CInt(Math.Floor(usedMilliseconds / (1.0 / 5000.0 * 1000.0) * Math.Floor(DataArray.Length / (usedMilliseconds / (1.0 / 5000.0 * 1000.0)))))
x_F_5000 += CSng(DataArray(cnt) * RealPart(5000.0 / 1000.0, Time_))
Time_ += (usedMilliseconds / DataArray.Length)
cnt += 1
End While
x_F_5000 /= cnt
'№ 15
cnt = 0
x_F_7500 = 0.0F
Time_ = 0.0
While cnt < CInt(Math.Floor(usedMilliseconds / (1.0 / 7500.0 * 1000.0) * Math.Floor(DataArray.Length / (usedMilliseconds / (1.0 / 7500.0 * 1000.0)))))
x_F_7500 += CSng(DataArray(cnt) * RealPart(7500.0 / 1000.0, Time_))
Time_ += (usedMilliseconds / DataArray.Length)
cnt += 1
End While
x_F_7500 /= cnt
continue_ = False
End Sub
Private Shared Function getRealPart(fw As Double, t As Double) As Double
Return Math.Cos(-2.0 * Math.PI * fw * t)
End Function