Author Topic: BASS.NET API 2.4.12.7  (Read 783512 times)

radio42

  • Posts: 4576
Re: BASS.NET API 2.4.7.4
« Reply #925 on: 22 Jun '11 - 10:52 »
The WaveForm class generates the 'static' wave form image only - it does not support direct scrolling as you need it.
So you need to implement that yourself.
But, that's not an easy one - but make a search here in the forum for "scrolling waveform" and you'll find various answers.
E.g. these:
https://www.un4seen.com/forum/?topic=11097.msg78229#msg78229
https://www.un4seen.com/forum/?topic=5581.msg37502#msg37502


nr1

  • Posts: 78
Re: BASS.NET API 2.4.7.4
« Reply #926 on: 23 Jun '11 - 12:17 »
Ok thx for your answer.

To contribute i created a WaveFormDemo application that shows the most important features of the WaveForm. Whats missing at the moment in this demo is the visualisation of the playing position (showing playing position line, scrolling waveform, ..).
Everyone feel free to add / correct features but make sure you also provide your changes here on the board.


nr1

  • Posts: 78
Re: BASS.NET API 2.4.7.4
« Reply #927 on: 24 Jun '11 - 08:04 »
@radio42: one more question:
i'm trying to save a rendered waveform as binary file by executing
Code: [Select]
wave.WaveFormSaveToFile(@"C:\Dokumente und Einstellungen\me\Desktop\BASS\WaveFormDemo\waveSavedByBass.txt",true);

The "waveSavedByBass.txt" file is created, but the filesize is always 4kb and the file's content is always " ".

It's also not working if i try to to this
Code: [Select]
byte[] waveForm = wave.WaveFormSaveToMemory(true);
as the byte array always is null after doing this.


If i use the "standard" saving (binary = false) both methods are working.

Any suggestions?

radio42

  • Posts: 4576
Re: BASS.NET API 2.4.7.4
« Reply #928 on: 24 Jun '11 - 08:30 »
That's strange.
I did a quick test here and it works fine without any issues.
Is the WaveForm fully rendered when you try to save it?
Ie. is the "wave.IsRendered" true? And what does "wave.WaveFormSaveToFile" return (true or false)?

nr1

  • Posts: 78
Re: BASS.NET API 2.4.7.4
« Reply #929 on: 24 Jun '11 - 08:51 »
Ie. is the "wave.IsRendered" true? And what does "wave.WaveFormSaveToFile" return (true or false)?

hello,

isRendered = true
wave.WaveFormSaveToFile = false

The file is anyway created although "wave.WaveFormSaveToFile" returns false.

radio42

  • Posts: 4576
Re: BASS.NET API 2.4.7.4
« Reply #930 on: 24 Jun '11 - 13:24 »
Ahh, now I see what's going wrong in your provided sample.
The "wave.FileName" property must actually be set before the "wave.WaveFormSaveToFile" method is being called.
Here is the updated section, which will actually work.

Code: [Select]
private void loadFile(String filename)
{
    Bass.BASS_StreamFree(playChannel);

    playChannel = Bass.BASS_StreamCreateFile(filename, 0L, 0L, BASSFlag.BASS_SAMPLE_FLOAT | BASSFlag.BASS_STREAM_PRESCAN);

    Task task = Task.Factory.StartNew(() =>
    {
if (System.IO.File.Exists(filename + ".wf"))
{
if (wave.WaveFormLoadFromFile(filename + ".wf", true))
{
zoomEnd = wave.FramesToRender;
drawWave();
}
}
else
{
int waveChannel = Bass.BASS_StreamCreateFile(filename, 0L, 0L, BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_FLOAT | BASSFlag.BASS_STREAM_PRESCAN);
wave.FileName = filename;
if (wave.RenderStart(waveChannel, false))
{
// save the waveform
wave.WaveFormSaveToFile(filename + ".wf", true);
}
Bass.BASS_StreamFree(waveChannel);
}
    });
}

However, in the next version I'll also allow the 'Filename' property to be null while saving the WavewForm!

nr1

  • Posts: 78
Re: BASS.NET API 2.4.7.4
« Reply #931 on: 24 Jun '11 - 17:59 »
thx a lot, now it's working  :)

ken

  • Posts: 739
Re: BASS.NET API 2.4.7.4
« Reply #932 on: 26 Jun '11 - 13:20 »
Hi Bernd,

Sometimes I get this error on:
Code: [Select]
Bass.BASS_StreamFree(_channel1);
Code: [Select]
CallbackOnCollectedDelegate was detected
Message: A callback was made on a garbage collected delegate of type 'Bass.Net!Un4seen.Bass.SYNCPROC::Invoke'. This may cause application crashes, corruption and data loss. When passing delegates to unmanaged code, they must be kept alive by the managed application until it is guaranteed that they will never be called.

Add stream to mixer like this:
Code: [Select]
_channel1 = Bass.BASS_StreamCreateFile(songcard.Filename, 0L, 0L, BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_FLOAT);
BassMix.BASS_Mixer_StreamAddChannel(_Mixer1, _channel1, BASSFlag.BASS_MIXER_DOWNMIX | BASSFlag.BASS_STREAM_AUTOFREE)

I do use a few BASS_ChannelSetSync, but not using BASS_ChannelRemoveSync (must I use remove?)

A try / catch don't help me here, so the app crashes, any ideas?

Versions of dlls:
Bass.NET 2.4.7.3
Bass 2.4.7.1
BassWASAPI 0.0.0.8
BassMix 2.4.5.0

/Ken

radio42

  • Posts: 4576
Re: BASS.NET API 2.4.7.4
« Reply #933 on: 26 Jun '11 - 20:33 »
How have you declared used the SYNCPROC?
It seems, that BASS is trying to invoke on a callback, which was already garbage collected in your code.
So you need to make sure, that at any time a SYNCPROC might be invoked your callback delegate still exists.

You do not nesseccarily have to remove a sync, as it will be freed, when the channel is freed - but any callback must still exist up until that time!

ken

  • Posts: 739
Re: BASS.NET API 2.4.7.4
« Reply #934 on: 27 Jun '11 - 08:31 »
How have you declared used the SYNCPROC?

declared SYNCPROC as private (top of the class) and I instance it before ChannelSetSync, but now I moved instance of SYNCPROC to the constructor of the class, and just reuse it.

this problem occurs rarely, but when it does app crash...

radio42

  • Posts: 4576
Re: BASS.NET API 2.4.7.4
« Reply #935 on: 27 Jun '11 - 09:11 »
Sounds like a race condition, eg. your class is being garbage collected (and as such your SYNCPROC member as well) before the stream is actually freed.
So what are you doing in your destructor of your class?
The only reason for a 'CallbackOnCollectedDelegate' exception is, that the callback delegate is already garbage collected but still used by BASS.

ken

  • Posts: 739
Re: BASS.NET API 2.4.7.4
« Reply #936 on: 27 Jun '11 - 13:14 »
So what are you doing in your destructor of your class?

parts of my "player class"

Code: [Select]

public class AudioEnginePlayback
{
       private int _channel1 = 0;
       private int _P1sync1 = 0;
       private int _P1sync2 = 0;
       private SYNCPROC _TrackSync;

        public AudioEnginePlayback()
        {
            _TrackSync = new SYNCPROC(OnTrackSync);
        }


        public void LoadTrack(LoadMediaClass Track)
        {
             
              Bass.BASS_StreamFree(_channel1);
              _channel1 = Bass.BASS_StreamCreateFile(Track.Filename, 0L, 0L, BASSFlag.BASS_STREAM_DECODE | BASSFlag.BASS_SAMPLE_FLOAT);
              BassMix.BASS_Mixer_StreamAddChannel(Track.Mixer1, _channel1, BASSFlag.BASS_MIXER_DOWNMIX | BASSFlag.BASS_STREAM_AUTOFREE);

               _P1sync1 = Bass.BASS_ChannelSetSync(_channel1, BASSSync.BASS_SYNC_POS, Track.MixPos, _TrackSync, new IntPtr(0));  //MixCue
               _P1sync2 = Bass.BASS_ChannelSetSync(_channel1, BASSSync.BASS_SYNC_END, 0, _TrackSync, new IntPtr(1)); //End of File

        }

        private void OnTrackSync(int handle, int channel, int data, IntPtr user)
        {

              Console.WriteLine("OnTrackSync: " + user.ToInt32());

              //top secret stuff here ;-)
         }
}


I think I code it by the "rules", or?

/Ken

radio42

  • Posts: 4576
Re: BASS.NET API 2.4.7.4
« Reply #937 on: 27 Jun '11 - 13:44 »
Yes and No.
Might it be possible within your app, that an actual instance of your 'AudioEnginePlayback' class might get disposed and garbage collected - but the 'track' is still playing?
If yes, it might be possible, that your 'AudioEnginePlayback' gets garbage collected whereas the SYNCPROC is still being used by BASS - resulting in the exception!

To be sure you might implement an IDisposbale pattern to your class and make sure the track is freed and removed!
E.g. add something like this to your class:
Code: [Select]
...
private bool disposed = false;
...
public void Dispose()
{
    Dispose(true);
    GC.SuppressFinalize(this);
}

private void Dispose(bool disposing)
{
    if(!this.disposed)
    {
        // remove _channel1 from the mixer!
        ....
        // and free the stream
        Bass.BASS_StreamFree(_channel1);

        disposed = true;
    }
}

~AudioEnginePlayback()
{
    Dispose(false);
}


ken

  • Posts: 739
Re: BASS.NET API 2.4.7.4
« Reply #938 on: 27 Jun '11 - 14:50 »
Yes and No.
Might it be possible within your app...

AudioEnginePlayback should not be disposed, I don't do it manually anywhere. But I try to add Dispose in my class.

Thanks!


radio42

  • Posts: 4576
Re: BASS.NET API 2.4.7.4
« Reply #939 on: 27 Jun '11 - 15:35 »
Even if you don't dispose the class manually, it will be disposed and as such subject to garbage collection when you don't keep any reference to your instance any longer.

nr1

  • Posts: 78
Re: BASS.NET API 2.4.7.4
« Reply #940 on: 29 Jun '11 - 18:44 »
A new WaveFormDemo is available:

Now containing also a zoomable scrolling waveform (realized by muntablues' code)
« Last Edit: 29 Jun '11 - 18:47 by nr1 »

BaseHead

  • Posts: 138
Re: BASS.NET API 2.4.7.4
« Reply #941 on: 26 Jul '11 - 08:34 »
Very cool WF demo! 
The one thing I hate about it is that it wasn't around when I popped the WF drawing in my app........hehehehe
Really Good job!   :)

Hey Bernd, any chance to get Quad, 6 channel and 8 channel drawing anytime soon?
That is one of my biggest BASS.NET wishes

thx!

Steve



radio42

  • Posts: 4576
Re: BASS.NET API 2.4.7.4
« Reply #942 on: 26 Jul '11 - 12:54 »
Currently there are no plans to add 4,6,8 channel WaveForm drawing...but I put it up on the wish list!

BaseHead

  • Posts: 138
Re: BASS.NET API 2.4.7.4
« Reply #943 on: 27 Jul '11 - 09:17 »
ok thx!
do you think there is anyway currently to fake it and grab the (L+R) (Center+LFE) (LS+RS) out of a 5.1 Interleaved file and draw 3 stereo pairs stacked?
I only see a way to feed a fileName into it now.

oh, one more WF request would be to bump up the WF resolution a tad.
I believe the smallest is 0.0001f
I'd like an option for maybe an extra decimal place for when we draw really tiny kick drum files to look a bit clearer

Great work man!

Steve
 

radio42

  • Posts: 4576
Re: BASS.NET API 2.4.7.4
« Reply #944 on: 27 Jul '11 - 13:48 »
The WaveForm class either takes a filename to be rendered or an already prepared decoding channel.
When giving a decoding channel to the WaveForm, it 'simply' calles BASS_ChannelGetData on it to calculate the WaveForm.

So what you might do is to create 3 independent decoding channels out of the same filename.
E.g. split a 6 channel audio file into 3 'stereo' decoding channels.
You might use the BASSmix addon to do so using the "BASS_Split_StreamCreate" method:
- create a regular decoding stream from your filename and use this as the splitter source stream
- create 3 decoding splitter streams using different 'chanmap' parameters to 'extract' the respective 2 channels

Regarding the WaveForm 'FrameResolution':
The minimum is 0.001 (1ms).
Meaning a line might represent only 1ms of 'sound'.
I don't see any reason/sense in increasing this value, as 1ms is already very small!
Even increasing this value wouldn't give you any better 'picture' - as the WaveForm always calculates the peak level value within the frame resolution. I.e. even if a 'tiny kick drum' would be less than 1ms in length, it would still result in the same peak level value.

Note, that you can define a 'frameStart' and 'frameEnd' parameter with the "CreateBitmap" method to draw only a 'portion' of the WaveForm - this might be used to 'zoom' into the WaveForm, giving you a 'clearer' picture.
« Last Edit: 27 Jul '11 - 13:57 by radio42 »

4drq

  • Posts: 2
Hi Bernd,

I've been playing with your Waveform-Example. In my example I draw a complete Waveform to a picturebox without zooming. When the user clicks in the picturebox with the waveform he jumps exactly to the position.... But when the mp3-file is for instance 02 hours and 09 minutes long, than the result of
     Dim pos As Long = wf.GetBytePositionFromX(e.X, Me.PictureBox1.Width, _zoomStart, _zoomEnd)
is negative and can't be used. (if the mp3-file is 01 hour and 25 min long then "pos" is positive and can be used....)

CodeSnippet:
Code: [Select]
Private _zoomStart As Integer = -1
Private _zoomEnd As Integer = -1
Private wf As WaveForm

Private Sub PictureBox1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) _
                 Handles PictureBox1.MouseDown
        If wf Is Nothing Then
            Return
        End If
        Dim pos As Long = wf.GetBytePositionFromX(e.X, Me.PictureBox1.Width, _zoomStart, _zoomEnd)
        If pos > -1 Then  Bass.BASS_ChannelSetPosition(_stream, pos)
End Sub

Any ideas/suggestions?

ThX in advance,
4drq
« Last Edit: 7 Aug '11 - 19:48 by 4drq »

radio42

  • Posts: 4576
Re: BASS.NET API 2.4.7.4
« Reply #946 on: 8 Aug '11 - 12:01 »
Can you please check the values for _zoomStart and _zoomEnd you are using in your example.
Could it be, that _zoomStart is bigger than _zoomEnd?
Else it could only be negative, if e.X is negative.

4drq

  • Posts: 2
Re: BASS.NET API 2.4.7.4
« Reply #947 on: 8 Aug '11 - 18:46 »
As you could see in my example _zoomstart and _zoomend are -1.

The waveform.GetBytePositionFromX(....) really seems to be buggy (if the mp3file is longer than about 2 hours)
The
   BASS_ChannelGetLength(_stream) and
   BASS_ChannelGetPosition(_stream)
   waveform.CreateBitmap(...)
are still working if using such a long mp3-file.
I have solved the problem without your waveform.GetBytePositionFromX(....) - function....

Example:
           Private _zoomStart As Integer = -1
           Private _zoomEnd As Integer = -1

           Private wf As WaveForm
          
           'Sub-Routine XY() - draw the waveform without zooming
           Me.PictureBox1.BackgroundImage = wf.CreateBitmap(Me.PictureBox1.Width, Me.PictureBox1.Height, _zoomStart, _zoomEnd, highQuality)
          
           Private Sub PictureBox1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseDown
                   If wf Is Nothing Then Return
                     'my version
                     Dim len As Long = Bass.BASS_ChannelGetLength(_stream)          ' length in bytes
                     Dim bpp As Double = len / CType(Me.PictureBox1.Width, Double) ' bytes per pixel
                     Dim pos As Long = CType(Math.Round(e.X * bpp), Long)             ' get byte position from mouse position
                     'old version (buggy) like in the Example "wfExample.vb" (not working if mp3file is longer than... about 2 hours)
                     'Dim pos As Long = wf.GetBytePositionFromX(e.X, Me.PictureBox1.Width, _zoomStart, _zoomEnd)
                     If pos > -1 Then Bass.BASS_ChannelSetPosition(_stream, pos)

           End Sub
« Last Edit: 9 Aug '11 - 17:51 by 4drq »

radio42

  • Posts: 4576
Re: BASS.NET API 2.4.7.4
« Reply #948 on: 9 Aug '11 - 08:23 »
I'll double check this!

TripleKill

  • Guest
Re: BASS.NET API 2.4.7.4
« Reply #949 on: 9 Aug '11 - 11:19 »
Hi everyone!

I've written a simple internet radio application for my WinCE PMP. If anybody's interested, and it doesn't contradict the License of BASS.NET, I can translate interface to English and publish source code here.

   

The left screenshot is the program working in Windows CE, and the right is on PC.
The change needed is to replace bass.dll with CE(ARM, MIPS) or PC(x86) version.
All other components are .NET CF and are cross-platform.

"Features" of the program:
- "Aggressive mode": if connection is somehow lost during playback, the program will try to reconnect every 10 seconds. This can be disabled through main menu.
- "Add to favourites" button: it doesn't add station in list, but places artist, song name and album in favourites.txt in program's folder. So, if you like the music being played, press that button, and you don't need to remember or write out the title.