Author Topic: WaveForm issues.  (Read 14121 times)

klimmbimm

  • Posts: 21
Re: WaveForm issues.
« Reply #25 on: 14 Oct '10 - 15:47 »
...
Thanks for the detailed description above! It helped me a lot to get into bass.
I followed the instructions and rendered a whole waveform directly when I load my file.
Now I want to build in additional functionality like a line showing me the actual position. But for this, I have to draw the whole waveform in the timer event again, haven't I?
And how could I manage to set "START" and "STOP" markers like in the Test_DSP sample? Seems like all graphical features need a timer.

My first idea was to overlay the waveform-picturebox with another picturebox with the BackColor "transparent". But at runtime the picturebox wasn't transparent noway.
Maybe this is more a .NET-specific problem, too, but I would be glad if you would give me assistance.

(By the way: I'm also from Germany, so if you prefer German, it would work too!)
« Last Edit: 14 Oct '10 - 15:50 by klimmbimm »

radio42

  • Posts: 4576
Re: WaveForm issues.
« Reply #26 on: 14 Oct '10 - 17:24 »
You might take a look to the provided Bass.Net C# sample called 'Simple' - this one is actually doing for what you are looking for.
This one draws the WaveForm to a picturebox BackgroudImage and the position marker to the regular image (as a transparent overlay).

klimmbimm

  • Posts: 21
Re: WaveForm issues.
« Reply #27 on: 4 Nov '10 - 13:28 »
...
So now you can use the "AutoScrollPosition" property of the panel control to bring a certain part of the picturebox in view.
The panel control can as such 'scroll' the picturebox and bring the relevant part into view.
...

I could scroll automatically with the current position of the stream by using Bass.BASS_ChannelGetPosition(_stream) with this code:
Code: [Select]
long pos = Bass.BASS_ChannelGetPosition(_stream); // position in bytes
bpp = len / (double)this.pictureBox1.Width; // bytes per pixel
pos -= _deviceLatencyBytes;
int x = (int)Math.Round(pos / bpp);  // position (x) where to draw the line
panel1.AutoScrollPosition = new System.Drawing.Point(x);

But how could I do the scrolling only if my Bass.BASS_ChannelGetPosition(_stream) runs out of my visible area (= the underlying panel)?

I tried something like this:
Code: [Select]
if ((x+5) % this.panel1.Width < 5)
   panel1.AutoScrollPosition = new System.Drawing.Point(x);
But this doesn't work, because a) "x" isn't a reliable divident of the "panel1.Width" and b) scrolling manually messes it up.

« Last Edit: 4 Nov '10 - 13:42 by klimmbimm »

radio42

  • Posts: 4576
Re: WaveForm issues.
« Reply #28 on: 4 Nov '10 - 13:47 »
The already mentioned sample also demos this - just take a look to the source code...

klimmbimm

  • Posts: 21
Re: WaveForm issues.
« Reply #29 on: 4 Nov '10 - 15:50 »
The already mentioned sample also demos this - just take a look to the source code...

The "Simple"-sample just looks like what I want to do when playing a stream and using the zoom. But in the source code it gets obvious, that the WaveForm is drawn every time the current position reaches the end of the "zoomDistance".
I have the big picturebox with the scrolling panel lying under. And I want to set the panel.AutoScrollPosition to the stream's position every time it runs out of the visible part of my picturebox.

aybe

  • Posts: 145
Re: WaveForm issues.
« Reply #30 on: 9 Nov '10 - 01:50 »
The code I posted above works, you set how many seconds you want to see before and after, etc ...

You need to know the relationships about pixels, seconds, image width, eventually ratio, to make this working well.


klimmbimm

  • Posts: 21
Re: WaveForm issues.
« Reply #31 on: 10 Nov '10 - 16:09 »
As you said, it is important to know the relationships about the playing position in pixels and some kind of a "visible area", which means the displayed part of the picturebox, which is not hidden outside the panel. I don't understand how to do this.
I think your code scrolls every Timer.Tick-event like mine.

What I don't understand in your code is this part in the Timer.Tick:
Code: [Select]
            /* Drawing bounds */
            double left = second - SecondsBefore;
            double secondsLeft = left < 0 ? 0 : left;
            double right = second + SecondsAfter;
            double secondsRight = right > seconds ? seconds : right;

            /* Resolution */
            long bytesL = Bass.BASS_ChannelSeconds2Bytes(_streamCreateFile, secondsLeft);
            long bytesR = Bass.BASS_ChannelSeconds2Bytes(_streamCreateFile, secondsRight);
            int fL = _waveForm.Position2Frames(bytesL);
            int fR = _waveForm.Position2Frames(bytesR);

            long samples = (bytesR - bytesL) / _waveForm.Wave.bps / 8 / _waveForm.Wave.chans; /* 16 bits stereo ! */
            double samplesPerPixel = (double)samples / pictureBox1.Width;
            double frameResolution = samplesPerPixel / 44100f;
What do you mean with "seconds you want to see before and after"?
Has this to do with the clipping-wise scrolling I want to do?

aybe

  • Posts: 145
Re: WaveForm issues.
« Reply #32 on: 10 Nov '10 - 16:30 »
Did you try it first ?

The seconds means, how far ahead/behind you'd like to see, that was my first version,
now what I do is I work by ratios much like in audio softwares 1:2048, etc ...

This ensures uniform rendering between songs, if you did set their width to 1000 px for example,
they would never really look the same, which is simply unacceptable in the case you're DJing

FrameResolution is the minimum possible level of detail, but in Miliseconds.
If you draw a very wide picture, there won't be much more details than what this property permits.

//First phase : right computation of the image width

Song length (seconds) > as samples > divide this by your ratio; you have your width
60 secs @ 44100 >> 2646000 samples / 2048 ratio == 1291 pixels wide

//2
Position = 30 seconds so 1f/2646000 * (30*44100) = 0.5
X= 0.5 * 1291  = 645.5

But in BASS you need to fetch this from byte position and the waveform like only frames
so I got rid of all this by always doing -1 to -1 framestart/end but i am absolutely certain
of the size of the image because i computed it through the ratio

Also, it's said in BASS, the exact length will be known only at the end of the stream
so analyze you're thing, after get the length of it
----
Personally I don't use a scrollbox anymore, I think it's crappy,
- I do compute all my forms with the lowest FrameResolution,
- create images by using ratios
- updating an image by directly writing through the means of pointers,
- the place it's happening is always the same width,
- and it's MUCH smoother thanks to InteropBitmap and CopyMemory but it's under WPF

got it now ?

also, you build the bitmap, not on every pixel scrolled, otherwise CPU 100%

Read all this thread again, you got the solution in it
« Last Edit: 10 Nov '10 - 16:34 by aybe »

klimmbimm

  • Posts: 21
Re: WaveForm issues.
« Reply #33 on: 17 Nov '10 - 09:53 »
I am still brooding on this.

I could see a 100% CPU load, if I scroll the bitmap on every pixel (respectively on every timer-tick event) - like you said.
That's why I wanted to know the "trick" how to scroll only, if my current position runs out the visible part of the panel.

By and by I would agree, that the scrolling picturebox is kind of a crappy solution, because I couldn't get it under control.

I didn't know much about Windows Presentation Foundation, so I started reading a book about this.

And furthermore I still don't understand your solution with "ratios". Is this how Audacity, Adobe Audition, AVS Audio Editor or any audio editor using NCT audio libraries do the zooming and scrolling? In this softwares the CPU load isn't that extensive as in my attemps when scrolling or zooming.

Is it too much to ask you for uploading your code?

Thank you very much for your help!

aybe

  • Posts: 145
Re: WaveForm issues.
« Reply #34 on: 18 Nov '10 - 16:00 »
I think it's nice to point out again the samples of BASS.NET API, as said radio42.
The TestDSP project does exactly what you're looking for ...

It does draw a new portion of the bitmap every N seconds,
that's the red line that's being drawn much more often; this is how you get no CPU 100%

For a big form size like the one you want, you do it like in the sample I said,
even Wavelab eats lot of CPU when you have direct scrolling at a narrow ratio.

Post your code here and I'll look at it,
and when you post, post everything, so I just have to copy/paste to try it.