B4J Question Signal spectrum

red30

Well-Known Member
Licensed User
Longtime User
It is required to display the traveling signal in time. The x-axis is the frequency (0..256 Hz). The y-axis is the time (0..60sec). Color to display the amplitude (from blue to red). Each new row (256 values) shifts the previous top (for one second). How can i do this? Any advice ...
 

Attachments

  • XxFzntVKPoQ.jpg
    XxFzntVKPoQ.jpg
    59.1 KB · Views: 346

klaus

Expert
Licensed User
Longtime User
Sincerely, the kind of signal doesnt matter.
I know that the kind of physical signal doesn't matter for the processing, I was just curius if the original signal is a sound, acceleration or something else.
In post#7 you speak about 256 sampels with one byte, in post #15 you speak about 256 samples with 2 bytes each ?
You say that the sampling frequency is 512Hz and you get every an Array every 125ms.
It will take 1 second to get 512 samples, this means that you have a 'big' overlapping in the Arrays.
Only 1/8 of the values is changing.
These questions just for my understanding, I always want to understand the entire problem or process.
 
Upvote 0

red30

Well-Known Member
Licensed User
Longtime User
Let the initial signal be an array of random numbers 512 samples with 2 bytes each (1024 bytes).
At first I said something else, because I did not know that there is your library, which can do a fast Fourier transform.
The whole task: an array of 1024 bytes (512 samples of 2 bytes) arrives, you need to make an FFT with a sampling frequency of 512 Hz. In the end, I want to get the spectrum of the signal (256 points (2 bytes, this is the amplitude)) and displayed on the graph in one line. The color will depend on the amplitude. The next 512 samples will come through 125mls and this will be the next line and so on. The total number of lines will be 480 (this is 1 minute for 125ml). Is 125mls enough to make the FFT and display it on the graph before the next 512 samples come? Could you help me with this? After FFT, what kind of bit is one point? If 1 byte, then the color will be displayed like this:
B4X:
    If Buf(i)<64 Then
        Colors.RGB (0,(Buf(i)*4),255)
    Else If Buf(i)>=64 And Buf(i)<128 Then
        Colors.RGB (0,255,(255-((Buf(i)-64)*4)))
    Else If Buf(i)>=128 And Buf(i)<192 Then
        Colors.RGB ((Buf(i)-128)*4,255,0)
    Else If Buf(i)>=192 Then
        Colors.RGB (255,255-((Buf(i)-192)*4),0)
    End If
Thank you a lot for helping
If something is not understandable please write me
 
Last edited:
Upvote 0

red30

Well-Known Member
Licensed User
Longtime User
klaus, in post #17 you gave a programme to me. Is it possible to show the number of row by focusing a mouse on Canvas?
 
Upvote 0

klaus

Expert
Licensed User
Longtime User
Is it possible to show the number of row by focusing a mouse on Canvas?
Sure, it is possible.

Attached a new version of the program.
FFT class included.
The rows are the results of FFT calculations.
4 sines with frequency variations.

upload_2017-3-28_18-16-7.png


The FFT Class will be published quite soon for B4x.
 

Attachments

  • jSpectrumGraph_1.zip
    5.4 KB · Views: 235
Upvote 0

red30

Well-Known Member
Licensed User
Longtime User
Klaus, thank you very much, you helped me greatly! I will try it tomorrow.
I have a question about the program in #17. I try to change Width and Height of the Canvas in Disigner but when I run a program, they don't change or change wrongly.Why?
 
Upvote 0

red30

Well-Known Member
Licensed User
Longtime User
In the new program (post # 24), the "number of rows" runs along with the "row." How can I make the "row" change only 0..60 (as well as the "column" (0..255))? A "Number of the series" went up.
 
Upvote 0

klaus

Expert
Licensed User
Longtime User
How can I make the "row" change only 0..60
I would suggest you to study the code and find it yourself to get experience.
Then if you have trouble, ask again.

A "Number of the series" went up.
What do you mean with this?
 
Upvote 0

red30

Well-Known Member
Licensed User
Longtime User
I would suggest you to study the code and find it yourself to get experience.
Then if you have trouble, ask again.
Well, I already have many attempts, but I will try again...
What do you mean with this?
Sorry, my English is bad, no questions anymore.

Now in the program the graffic moves up, and I need it to move down, so any ideas or hints please.
 
Upvote 0

klaus

Expert
Licensed User
Longtime User
Now in the program the graffic moves up ...
That's what you asked for in the first posts!

Now, again, look at how and where the rows are drawn and moved.
And you will for find how to invert the drawing.
 
Upvote 0

red30

Well-Known Member
Licensed User
Longtime User
Can you explain how DrawRow works? To start the graph at the top, I change "y = y0 - dy" to "y = dy" in DrawRow. Right? But I do not understand how MoveRows works. Can you explain me please?
 
Upvote 0

klaus

Expert
Licensed User
Longtime User
The top coordinate is y1.
So you could use this:
B4X:
For col = 0 To 255
    x = x0 + col * dx
    cvsGraph.DrawRect(x, y1, dx, dy, RowColors(col), True, 1)
Next

And MoveRows:
You must change the values below in the Private Sub InitGraph routine.
B4X:
MoveWidth = 256 * dx
MoveHeigth = 59 * dy
MoveSourceTop = y1
MoveDestTop = y1 + dy
The MoveRows routine remains the same:
B4X:
Private Sub MoveRows
    cvsGraph.DrawImage2(cvsGraph.Snapshot, x0, MoveSourceTop, MoveWidth, MoveHeigth, x0, MoveDestTop, MoveWidth, MoveHeigth)
End Sub
cvsGraph.DrawImage2(Image, SourceLeft, SourceTop, SourceWidth, SourceHeigth, DestLeft, DestTop, DestWidth, DestHeigth)
cvsGraph.DrawImage2 copies a part of a source image, cvsGraph.Snapshot in your case, with the coordinates of the source rectangle to the cvsGraph Canvas in a rectangle with the destination coordinates.

So in your case, you want to copy the upper 59 rows one row below, therefore:
MoveWidth = 256 * dx : the width of the 256 samples
MoveHeigth = 59 * dy : height of 59 rows
MoveSourceTop = y1 : source top is the top line coordinate
MoveDestTop = y1 + dy : destination top is one row below the top line
SourceLeft = DestLeft = x0 : left coordinate of the image
SourceTop = MoveSourceTop = y1: top line
DestTop = MoveDestTop + y1 + dy one row below the top line
SourceWidth = DestWidth = MoveWidth = 256 * dx the width of the 256 samples
SourceHeight = DestHeight = MoveHeigth = 59 * dy the height of 59 rows

I hope that this is clear.
 
Upvote 0

red30

Well-Known Member
Licensed User
Longtime User
When I make the number of rows 480, when counting the number of rows, I get from 1 to 479 Why? Where is one line lost?
 
Upvote 0

sorex

Expert
Licensed User
Longtime User
maybe you plot, move, clear. it's move, clear, plot that you need to do or you'll lose a line.
 
Upvote 0

red30

Well-Known Member
Licensed User
Longtime User
Where and how do you set the number rows?
Without seeing your code it's impossible to give a concrete answer!
OMG sorry I havent noticed that the code hasnt beed applied, my miss.
 

Attachments

  • jSpectrumGraph.zip
    61.8 KB · Views: 200
Upvote 0

klaus

Expert
Licensed User
Longtime User
I suggest you the following.
Add Private NumberOfRows As Int in Process_Globals
And modify InitGraph like below:
B4X:
Private Sub InitGraph
    NumberOfRows = 480
    dx = (cvsGraph.Width - 40) / 256
    x0 = (cvsGraph.Width - 256 * dx) / 1.8
    x1 = x0 + 256 * dx
    dy = (cvsGraph.Height - 40) / NumberOfRows
    y0 = cvsGraph.Height - (cvsGraph.Height - NumberOfRows * dy) / 1.8
    y1 = y0 - NumberOfRows * dy - 1
- 1 in the last line is new.
 

Attachments

  • jSpectrumGraph_2.zip
    5.5 KB · Views: 238
Upvote 0
Top