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

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
0
0

I have always used a rectangle with .Right and .Bottom set to pic.Width and pic.Height, and that works fine.
I also cache hwnd, hdc and this rectangle in memory so you don’t have to access object properties each time.

I haven’t used timers (windows or api), I just use a Do … Loop with a doevents and some waiting code with a SleepEx at the end to get a constant framerate.

The only thing that would be nice is a function like SleepEx, but much more accurate (when you call sleepex with 1 ms it might take 3 to 5 ms).
I’ve ever seen an example that seemed to be using a function ‘NanoSleep’, but I haven’t found that function yet.

  • You must to post comments
0
0

I have made a spectrum analysis that is fast enough, using windows API for the lines and stuff.

‘Declarations
Private Declare Function CreateSolidBrush Lib “gdi32” (ByVal crColor As Long) As Long
Private Declare Function FillRect Lib “user32” (ByVal hdc As Long, lpRect As Rect, ByVal hBrush As Long) As Long
Private Declare Function DeleteObject Lib “gdi32” (ByVal hObject As Long) As Long
Private Declare Function LineTo Lib “gdi32” (ByVal hdc As Long, ByVal X As Long, ByVal Y As Long) As Long
Private Declare Function MoveToEx Lib “gdi32” (ByVal hdc As Long, ByVal X As Long, ByVal Y As Long, lpPoint As Any) As Long

‘Just put this in a timer

'This updates the Spectrum and the VU

Dim rct As Rect 'For clearing
Dim hBr As Long
Dim hdc As Long
'The spectrum is only set for 270
'floats because that is how big my
'picturebox is, and most of all the
'data after 128 floats is boring anyways.
Static Spectrum(270) As Single

Dim Y As Integer

'First set the rectangle for clearing
rct.Bottom = picSpectrum.Height
rct.Left = 0
rct.Right = picSpectrum.Width
rct.Top = 0

'Get the spectrum from the FFT
Call GetSpectrum(Spectrum)

'Set the HDC of the picturebox
hdc = picSpectrum.hdc

'Create the rectangle
hBr = CreateSolidBrush(&H804000)
FillRect hdc, rct, hBr
DeleteObject hBr

'Loop through the Spectrum and plot
'each line
For Y = 0 To 270
    'Change the current position
    MoveToEx hdc, Y, 0, ByVal 0&
    'Create the vertical line
    LineTo hdc, Y, (picSpectrum.ScaleHeight - Spectrum(Y) * picSpectrum.ScaleHeight)
Next Y

'Refresh the picturebox
picSpectrum.Refresh

This works pretty good, but what I’m trying to do is make the lines wider so that each line is maybe 10 pixels wide. Currently each spectrum line is 1 pixel wide.

Thanks

  • You must to post comments
0
0

InvalidateRect and similar other API calls are similiar to doing a pic.refresh but much much more faster, and because u supply the acutal rect area where the refresh is done, its even faster because it only updates the area where u worked (if u define your rect correctly)

Shoudl be able to find more detailed information on them by searching the M$ web site and reading the GDI stuff, its chalk full of some very interesting calls.

I did look at your example, and found it to be a decent, however fairly complex to follow bit of code, however the code does preform nicely.

++Cire.

P.S…InvalidateRect is really only useful when u need to do refreshes, acutal drawing code like lines, rectfills, ect do not need to be refreshed, unless you are working with a pic that does not have autorefresh on or something similar to that.

  • You must to post comments
0
0

So how would I go about using Do Loop??? The way I have it now is in a timer using For Next. It loops through the width of picturebox and plots each line, and then refreshes itself with the timer. So if you use Do Loop how would you refresh it. How do you use SleepEx?? Thanks.

  • 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
Showing 1 - 20 of 24 results
Your Answer

Please first to submit.