Author Topic: Make Picturebox width increase as rendering waveform recording  (Read 154 times)

Chris Oakley

  • Posts: 17
Folks,

I'm using Bass.Net and I've looked through the forum and the help file and I might be missing something, but I can't see how I can increase the width of a picturebox to match the recording I'm rendering.

Essentially what I'm trying to achieve is have a picture box on the form and then as recording is happening the waveform for that live recording is rendered to the picturebox in full, with the picturebox width increasing to accommodate the new data to be recorded. I don't want it moving on every so many seconds so it's scrolling along within the picturebox or a cycle.

There must be a way to do this. Anyone got any pointers?

:)

radio42

  • Posts: 4576
You must calculate the size of the picture box yourself.
Bass.Net just renders the WaveForm to an existing UI component; but it doesn't manipulates its size.
Use the 'FramesRendered' and the 'FrameResolution' properties to determine this resp. use the 'Frame2Seconds' and the 'Position2Frames' methods to convert size/position to a frame resp. the other way around.

Chris Oakley

  • Posts: 17
This is great. The only issue I have is when I render the waveform onto the picturebox it's not quite steady as it progresses. It sort of wobbles a little back and forth.

I use:

Code: [Select]
WF.RenderStartRecording(recChannel, 0.01F, 0.01F)
to create a constantly building waveform. Is this correct?

radio42

  • Posts: 4576
I am not sure what you mean by 'wobbling' - here it doesn't wobble.
The StartRecording parameters basically just defines the callback frequency and the precision to use for the rendering.
The size of the final picturebox can of course only be determined once the recording has finished.

Chris Oakley

  • Posts: 17
Yeah sorry I suppose that doesn't help too much. Okay, probably easier if I post the code. This bit of code is in a 25 ms interval timer: (ZoomLevel is set to 50 which makes 1 second = 50 pixels)

Code: [Select]
        Dim l As Single = (WF.FramesRendered * WF.FrameResolution) * ZoomLevel
        pctWave(1).Width = l
        DrawWave()

This is the DrawWave sub:

Code: [Select]
    Private Sub DrawWave()
        Dim Picture As PictureBox = pctWave(1)
        If Not (WF Is Nothing) Then
            Picture.BackgroundImage = WF.CreateBitmap(Picture.Width, Picture.Height, -1, -1, False)
        Else
            Picture.BackgroundImage = Nothing
        End If
    End Sub

And this is the code that starts everything off:

Code: [Select]
    Private Sub StartRecording()

        recChannel = Bass.BASS_RecordStart(44100, 2, BASSFlag.BASS_RECORD_PAUSE, _myRecProc, IntPtr.Zero)
        WF.RenderStartRecording(recChannel, CSng(WF.FrameResolution), CSng(WF.FrameResolution))
        Bass.BASS_ChannelPlay(recChannel, False)
        tmrRecord.Enabled = True

    End Sub


And the recording handle:

Code: [Select]
    Private Function MyRecording(handle As Integer, buffer As IntPtr, length As Integer, user As IntPtr) As Boolean

        If length > 0 AndAlso buffer <> IntPtr.Zero Then
            WF.RenderRecording(buffer, length)
        End If
        Return True

    End Function

If you use that code you will see as the picture box width increases in size to accommodate the rendered wave the waveform doesn't stay fixed / steady. It sort of fluctuates.

radio42

  • Posts: 4576
Of course, as you are doing live recording rendering, the number of rendered frames do increase over time.
However, it seems you are using a 25ms timer to do the redraw/refresh and resize of the pictureBox.
This timer is unrelated to the effective recording.
This means, that it is not ensured/guaranteed, that whenever the timer event is called, that the effective recording audio also has passed/updated exactly 25ms.
Thus sometimes the picturebox width is advancing more and sometimes less than exactly 25ms.

To resolve this you might for example also use your BASS recording callback to trigger the redraw instead of using an extra timer.

Chris Oakley

  • Posts: 17
Not a bad idea. The trouble is the recording callback is causing it to cross thread. Am I best trying to use an Invoke here or is there another trick?

radio42

  • Posts: 4576
There is no trick, you must use Invoke or better BeginInvoke to make sure its then executed on the UI thread.