0
0

This uses the Pset function so it doesn’t display lines. But it is extremely fast. If anyone can tell me how to make a better spectrum analyzer without losing speed I would be very interested.

Just put it in a timer with interval of 1.

Static Spectrum(128) As Single

Call GetSpectrum(Spectrum)
Dim Y As Integer

PicSpectrum.Cls

For Y = 0 To 128
    PicSpectrum.PSet (Y, PicSpectrum.ScaleHeight - Spectrum(Y) * 100)
Next Y
  • You must to post comments
0
0

Just use Fillrect for your lines too :

[code:38w3695b]
rct.Bottom = picSpectrum.ScaleHeight
hBr = CreateSolidBrush(&H804000)
For X = 0 To 270
rct.Left = X5
rct.Top = rct.Bottom – Spectrum(Y) * rct.Bottom
rct.Right = X
5 + 4
FillRect hdc, rct, hBr
Next Y
DeleteObject hBr
[/code:38w3695b]

The reason I put picSpectrum.ScaleHeight outside of the for loop is because requesting properties from controls is a lot slower then using local or global variables.

  • You must to post comments
0
0

Thanks, it is a bit complex to follw but it works really well I think. So then I will use invalidaterect now instead of Refresh, thanks for the tip.

  • You must to post comments
0
0

Thanks Adion. Your code has improved the performance of the spectrum. Just to point out that variable X in the code is actually variable Y.

Any other tips on how to design a fast, smooth and efficient spectrum. I was wondering on how to have peak points with the spectrum.

  • You must to post comments
0
0

Heres the new code:

[code:gf724k64]

‘Create the rectangle for clearing the
‘Spectrum
ClsSpecHBR = CreateSolidBrush(&HFD7E00)
‘Drawing the spectrum
DrSpecHBR = CreateSolidBrush(&H804000)

‘Refresh the rect
InvalidateRect picSpectrum.hwnd, rct, True
‘Loop through the Spectrum and plot
‘each line
rct.Bottom = picSpectrum.ScaleHeight
For Y = 0 To 45
Spectrum_Peaks(Y) = Spectrum_Peaks(Y) * 0.98
If Spectrum(Y) > Spectrum_Peaks(Y) Then Spectrum_Peaks(Y) = Spectrum(Y)
rct.Left = Y * 5
rct.Top = rct.Bottom – Spectrum(Y) * rct.Bottom
rct.Right = Y * 5 + 4
FillRect hdc, rct, DrSpecHBR
For X = 1 To 4
SetPixelV hdc, (Y * 5 + X) – 1, (rct.Bottom – Spectrum_Peaks(Y) * rct.Bottom), &HFFD8B0
Next X
Next Y[/code:gf724k64]

Thanks!

  • You must to post comments
0
0

I changed the variable name to X, because it is the X-axis you are looping over.

Peaks can easily be done with a second array,

[code:2zpv8tp8]
For X = 0 to 270
‘Fade the peaks (change 0.99 to another value for slower or faster fallback)
Spectrum_Peaks(x) = Spectrum_Peaks(x) * 0.99
‘Make the peaks the highest points
If Spectrum(x) > Spectrum_Peaks(x) Then Spectrum_Peaks(x) = Spectrum(x)
‘Drawing code here
Next
[/code:2zpv8tp8]

  • You must to post comments
0
0

Doesn’t it make more sense to refresh the picture AFTER you have drawn the spectrum?
The way it now is, the most recent picture will only be shown when you are already drawing the next one, so now you have a latency of one frame.

  • You must to post comments
0
0

Thanks for that, that works out very nicely, makes it look much like Winamp’s.

Thanks again.

  • You must to post comments
0
0

Yeah, but for some reason if I move the invalidaterect call after the drawing procedure then it doesnt work at all, and if I completely remove the call then it still doesnt work. The only way that I got it to work is to put it before the drawing code. Any suggestions?

  • You must to post comments
0
0

For drawing the peaks you could just use the SetPixelV API to draw a single dot above each line, just a thought. It’s much faster than PSET.

Also, the thing about the spectrum part of this is that it isn’t actually plotting 270 lines, so it’s wasting time by calculating all those extra lines without actually plotting them because they are all 5 pixels wide or so. Maybe I’m wrong, but I think that it is only plotting maybe 55 lines

Paranoid Android

  • You must to post comments
0
0

Maybe you also have to add a DoEvents after InvalidateRect?
I have replaced all Refresh calls in my program to InvalidateRect, and it seems to work, as long as you make sure windows gets time to update it now and then, which can be done by adding a DoEvents.

  • You must to post comments
0
0

Thanks Adion.

Paranoid_Android, can you please post your code including the SetPixelV drawing code. Thanks!

  • You must to post comments
0
0

Ok, I tried your idea and still no luck, what could I be doing wrong??? Could you post a bit of your code to see what I could be doing? Thanks!

  • You must to post comments
0
0

I changed 270 to 45 because, drawing 270 lines would be useless, 45 is a nice small number.

[code:16jeim7o]
Private Declare Function SetPixelV Lib "gdi32" (ByVal hdc As Long, ByVal X As Long, ByVal Y As Long, ByVal crColor As Long) As Long

Static Spectrum(45) as single
Static Spectrum_Peaks(45) as single

Call GetSpectrum(Spectrum)

For Y = 0 To 45
Spectrum_Peaks(Y) = Spectrum_Peaks(Y) * 0.9
If Spectrum(Y) > Spectrum_Peaks(Y) Then Spectrum_Peaks(Y) = Spectrum(Y)

rct.Left = Y * 5
rct.Top = rct.Bottom – Spectrum(Y) * rct.Bottom
rct.Right = Y * 5 + 4
FillRect hdc, rct, hBr

For X = 1 To 4
SetPixelV hdc, (Y * 5 + X) – 1, (rct.Bottom – Spectrum_Peaks(Y) * rct.Bottom), &HFFD8B0
Next X

Next Y[/code:16jeim7o]

I modified my post to show how to create full lined background peaks instead of just dots.

Have fun!

  • You must to post comments
0
0

I think my code is very similar to the code already given :

Draw some stuff with the picture’s hdc,
InvalidateRect on the whole picture with the picture’s hwnd
Doevents

The picture’s redraw property is set to true.

  • You must to post comments
0
0

You might also try looking at the InvalidateRect api call to help improve refresh rates, and precalculate your rects, so you don’t have to build them each time. Furthermore your brushes and pens could be created at load and then deleted at unload time, however remember each time you leave a function to select the saved pen/brush (unless using fillRect). Remeber the more calculations and commands that you can remove from loops the better the preformance.

++Cire.

  • You must to post comments
0
0

Hmmm, well, that is exactly what I ahve too, I’ll go look at my code again to see if I missed something… Thanks.

  • You must to post comments
0
0

Could you explain how InvalidateRect works??? It sounds useful to me but I’m unsure of how to use it. Thanks.

  • You must to post comments
0
0

InvalidateRect must have the rect defined correctly if you use it with the wrong hwnd or the rect incorrectly defined then it will fail.

Keep in mind that a picturebox is more or less another window and you might need to calculate your rects based on your forms rect def, and then find the childwindow of the picturebox. (if this makes since). Try using the api to attain the rect of the child window of a form. These 2 api functions should help alleviate your pain.

[code:2psecwvj]
Public Declare Function GetClientRect Lib "user32" (ByVal hwnd As Long, lpRect As RECT) As Long
Public Declare Function GetWindowRect Lib "user32" (ByVal hwnd As Long, lpRect As RECT) As Long
[/code:2psecwvj]

Yes this seems like alot more work, yet it is blazingly faster. One other suggestion I might make is that you get rid of VB timers they are the most inaccurate piece of junk ever written by M$ If you use the api timers you can collect the hwnd of the owner, from it attain the DC draw to it and whats REALLY nice is not have to refresh.

++Cire.

  • You must to post comments
0
0

I think not using Picture1.Cls, but instead using DrawRectangle
[code:l62ffl3g]
hBr = CreateSolidBrush(Colour)
FillRect hdc, rct, hBr
DeleteObject hBr
[/code:l62ffl3g]

(rct is a RECT, the declarations for these functions and type can be found using the win32 api viewer, or the win32.tlb type library)

If you also use this to draw lines instead of pixels with PSet it might look a bit better withouth losing too much speed.

And to make sure it looks good, enable the picture’s AutoRedraw property, and add
Picture1.Refresh
at the end of the code.

  • You must to post comments
0
0

I moved the CreateSolidBrush calls to Form Load, and them moved the DeleteObject calls into Form Unload. I placed the InvalidateRect call into the timer, although I’m not sure that I did it correctly. The refresh rates are much better now, there is absolutely no pauses or skipping in the spectrum now. Thanks for your tips.

  • You must to post comments
Showing 1 - 20 of 24 results
Your Answer

Please first to submit.