BASS.NET API 2.4.18.2

Started by radio42,

radio42

Looks all fine - and if it is working no issues!

teq

#1521
Hi there! I'am using bass net with Unity, and everything was fine before i switched to 64 bit builds(Mono->IL2CPP).
My app is suddenly crashing(only on mobile device android), when i play tracks and saving cache to disk.
Here is my main streamHandle
streamHandle = Bass.BASS_StreamCreateURL(url,
0,
BASSFlag.BASS_STREAM_DECODE,
_trackDownloadProc,
IntPtr.Zero);
Then a create fx stream, cause i am using changing tempo and others features
streamTempoFX = BassFx.BASS_FX_TempoCreate(streamHandle , BASSFlag.BASS_FX_FREESOURCE);
If in BASS_StreamCreateURL i use null instead of _trackDownloadProc everything works fine, but with _trackDownloadProc app can crash, it happens in different times, and sometimes works really long, sometimes crashes on 5-6 track play.

Here is _trackDownloadProc
[AOT.MonoPInvokeCallback(typeof(MonoPMessageDelegate))]
    //private void TrackDownloadProc(IntPtr buffer, int length, IntPtr user)
    private static void TrackDownloadProc(IntPtr buffer, int length, IntPtr user)
    {
        if (_cachingTrackFilename.IsNullOrWhitespace())
        {
            return;
        }

        if (_fs == null)
        {
            _fs = File.OpenWrite(_cachingTrackFilename);
        }

        if (buffer == IntPtr.Zero)
        {
            _fs.Flush();
            _fs.Close();

            if (_fs != null)
            {
                ((IDisposable) _fs).Dispose();
            }

            if (lastStreamingTrackModel != null)
            {
                bool trackExist = File.Exists(@lastStreamingTrackModelFilePath);
                long trackFileSize = trackExist ? new FileInfo(@lastStreamingTrackModelFilePath).Length : 0;

                if (trackExist)
                {
                   
                    if (trackFileSize != lastStreamingTrackModel.fileSize)
                    {
                        try
                        {
                            FileManager.Instance.DeleteFile(lastStreamingTrackModelFilePath);
                        }
                        catch (Exception e)
                        {
                            Debug.LogError($"Error while delete not fully TrackDownloadProc track error = {e.Message}, lastStreamingTrackModelFilePath = {lastStreamingTrackModelFilePath}");
                            MyCrashlytics.Instance.LogNonFatal(new Exception("ClipPlayer TrackDownloadProc Error"), $"error = {e.Message}", true);
                        }
                    }
                    else
                    {
                        lastStreamingTrackModel.waitingLoading = false;
                        lastStreamingTrackModel.waitingForDownloading = false;
                        lastStreamingTrackModel.assetBundlesLoading = false;
                        lastStreamingTrackModel.loading = false;
                        lastStreamingTrackModel.loaded = true;
                        lastStreamingTrackModel.cached = true;
                    }
                }
                else
                {
                    lastStreamingTrackModel.waitingLoading = false;
                    lastStreamingTrackModel.waitingForDownloading = false;
                    lastStreamingTrackModel.loading = false;
                    lastStreamingTrackModel.loaded = false;
                    lastStreamingTrackModel.cached = false;
                }
            }
        }
        else
        {
            if (_trackLoadedData == null || _trackLoadedData.Length < length)
            {
                _trackLoadedData = new byte[length];
            }

            Marshal.Copy(buffer, _trackLoadedData, 0, length);
            _fs.Write(_trackLoadedData, 0, length);
        }
    }

Before each play iteration i make
Bass.BASS_ChannelStop(streamHandle );
Bass.BASS_StreamFree(streamHandle );
Bass.BASS_ChannelStop(streamTempoFX);
Bass.BASS_StreamFree(streamTempoFX);
Also, i set _trackLoadedData = null before each iteration.
I noticed that crash on mobile happens, when click between tracks very fast, so seems that something can not get in time. For example, if i click very fast in Editor i got this error, but not crash
IOException: Invalid handle to path "pathToFile"
System.IO.FileStream.FlushBuffer () (at <599589bf4ce248909b8a14cbe4a2034e>:0)
System.IO.FileStream.WriteInternal (System.Byte[] src, System.Int32 offset, System.Int32 count) (at <599589bf4ce248909b8a14cbe4a2034e>:0)
System.IO.FileStream.Write (System.Byte[] array, System.Int32 offset, System.Int32 count) (at <599589bf4ce248909b8a14cbe4a2034e>:0)
or ObjectDisposedException: Cannot access a disposed object.
Object name: 'Stream has been closed'.

on this line
_fs.Write(_trackLoadedData, 0, length);
I call BASS_StreamCreateURL() in different thread, cause it main it stucks the UI.
_trackDownloadProc = new DOWNLOADPROC(TrackDownloadProc); i tried in main and different thread, no matters.

So, i am curios what is going wrong. Unity IL2CPP bug(cause in Mono it works ok), or i doing something not safely. How should i properly handle multiple calls, i mean clean what i have to clean? =) My hunch is that, if i click play too fast between tracks that FileStream Write() continue use old, flushed file, so i need somehow quickly abort DOWNLOADPROC when click on new file. Thanks.

Guest

I tried the following program for HLS streaming, but got an error.
Bass.BASS_SetConfig (BASSConfig.BASS_CONFIG_HLS_DELAY, 15);
Is BASS.NET supported?

radio42

You need to cast the current value like this: (BASSConfig)0x10900

The constants will be added in the next version.

Guest

Ian @ un4seen

BASS_CONFIG_HLS_DELAY is defined as 0x10902 (in BASSHLS.H), so you would use (BASSConfig)0x10902 in this case.

sirnaysayer

#1526
I am using the .NET Core version with .NET Core 3.1, however the Visuals class is not showing up with Intellisense. Is the Visuals functionality not included with the .NET Core version of the API?

Edit: I was able to decompile Visuals.cs with ILSpy from the 4.5 version of the library. I simply replaced the Windows.Forms reference with compatible code and it seems to be working. Editing my message in case anyone else had a similar idea.

radio42

No, .Net Core doesn't support such functionality - thus it has to be excluded.

toob

I'm trying to play various .ogg files but none of them play with my code. I get BASS_ErrorGetCode 41 Unsupported file format , yet I can open the files in other players like GoldWave where the files play fine. What am I doing wrong? Note .mp3 files plays fine using the same code.
res = Bass.BASS_StreamCreateFile(fname, 0, 0, BASSFlag.BASS_STREAM_DECODE Or BASSFlag.BASS_SAMPLE_SOFTWARE)
res = 0 when .ogg file
fname is the full path and file name.

Hex from the beginning of the file, if that helps:
00000000h: 56 44 4A 00 3E 03 00 00 23 01 00 00 02 F6 00 00 ; VDJ.>...#....ö..
00000010h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
00000020h: 4F 04 B9 3E E2 8C 1A 3C 00 00 00 00 00 00 00 00 ; O.¹>âŒ.<........
00000030h: EC 51 B8 1E 85 EB 07 40 EC 51 B8 1E 85 EB 07 40 ; ìQ¸....ë.@ìQ¸....ë.@
00000040h: EC 51 B8 1E 85 EB 07 40 E1 AC 96 3F 00 00 00 00 ; ìQ¸....ë.@ᬖ?....
00000050h: 00 00 00 00 25 F7 00 00 49 2D 02 00 70 00 00 00 ; ....%÷..I-..p...
00000060h: B3 00 00 00 F4 1C 0C 00 00 00 00 00 00 00 00 00 ; ³...ô...........
00000070h: 43 3A 5C 55 73 65 72 73 5C 52 75 6E 65 5C 44 6F ; C:\Users\Rune\Do
00000080h: 63 75 6D 65 6E 74 73 5C 56 69 72 74 75 61 6C 44 ; cuments\VirtualD
00000090h: 4A 5C 73 6F 75 6E 64 20 73 61 6D 70 6C 65 72 20 ; J\sound sampler
000000a0h: 73 6F 75 72 63 65 73 5C 43 79 6D 61 74 69 63 73 ; sources\Cymatics
000000b0h: 46 72 65 65 48 61 6C 6C 6F 77 65 65 6E 56 6F 63 ; FreeHalloweenVoc
000000c0h: 61 6C 73 2D 56 31 2D 69 38 72 5C 43 79 6D 61 74 ; als-V1-i8r\Cymat
000000d0h: 69 63 73 20 2D 20 46 72 65 65 20 48 61 6C 6C 6F ; ics - Free Hallo
000000e0h: 77 65 65 6E 20 56 6F 63 61 6C 73 5C 50 68 72 61 ; ween Vocals\Phra
000000f0h: 73 65 73 5C 43 79 6D 61 74 69 63 73 20 2D 20 56 ; ses\Cymatics - V
00000100h: 61 72 69 6F 75 73 20 50 68 72 61 73 65 20 2D 20 ; arious Phrase -
00000110h: 48 61 70 70 79 20 48 61 6C 6C 6F 77 65 65 6E 2E ; Happy Halloween.
00000120h: 77 61 76 4F 67 67 53 00 02 00 00 00 00 00 00 00 ; wavOggS.........
00000130h: 00 5E 88 7A BA 00 00 00 00 6E EE B4 9F 01 1E 01 ; .^ˆzº....nî´Ÿ...
00000140h: 76 6F 72 62 69 73 00 00 00 00 02 44 AC 00 00 00 ; vorbis.....D¬...
00000150h: 00 00 00 00 EE 02 00 00 00 00 00 B8 01 4F 67 67 ; ....î......¸.Ogg
00000160h: 53 00 00 00 00 00 00 00 00 00 00 5E 88 7A BA 01 ; S..........^ˆzº.
00000170h: 00 00 00 EC 7E 79 17 10 36 FF FF FF FF FF FF FF ; ...ì~y..6ÿÿÿÿÿÿÿ
00000180h: FF FF FF FF FF FF FF 71 03 76 6F 72 62 69 73 0D ; ÿÿÿÿÿÿÿq.vorbis.
00000190h: 00 00 00 4C 61 76 66 35 37 2E 37 31 2E 31 30 30 ; ...Lavf57.71.100
000001a0h: 01 00 00 00 15 00 00 00 65 6E 63 6F 64 65 72 3D ; ........encoder=
000001b0h: 4C 61 76 66 35 37 2E 37 31 2E 31 30 30 01 05 76 ; Lavf57.71.100..v
000001c0h: 6F 72 62 69 73 2B 42 43 56 01 00 08 00 00 00 31 ; orbis+BCV......1
000001d0h: 4C 20 C5 80 D0 90 55 00 00 10 00 00 60 24 29 0E ; L ŀАU.....`$).
000001e0h: 93 66 49 29 A5 94 A1 28 79 98 94 48 49 29 A5 94 ; "fI)¥"¡(y˜"HI)¥"
000001f0h: C5 30 89 98 94 89 C5 18 63 8C 31 C6 18 63 8C 31 ; Å0‰˜"‰Å.cŒ1Æ.cŒ1

Ian @ un4seen

That isn't a standard OGG file, which should begin with "OggS". From the "VDJ" signature, it appears to be VirtualDJ file? It looks like the DWORD at offset +8 tells where the OGG data begins. If so, you could read that from the file and set the BASS_StreamCreateFile "offset" parameter to it.

toob

Yes I think these files contain DJ samples and VDJ have adjusted the headers like you say. GoldWave is clever enough to detect that when reading in the file and states it's ogg, as they play without issue. I've Tried manually editing the header without luck so perhaps VDJ do something else later in the file. So for now I'm duplicating as mp3 to get round it, not ideal but it's a solution. Thanks  ;D

jasona

#1531
Having some marshaling issues when targeting netcoreapp3.1 with the following code:
            Bass.LoadMe();
            BassFx.LoadMe();
            Bass.BASS_Init(0, 44100, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero, Guid.Empty);

            var channel = Bass.BASS_StreamCreateFile(@"music.mp3", 0, 0, BASSFlag.BASS_STREAM_DECODE);

            var fx = Bass.BASS_ChannelSetFX(channel, BASSFXType.BASS_FX_BFX_VOLUME_ENV, 1);
            var success = Bass.BASS_FXSetParameters(fx, new BASS_BFX_VOLUME_ENV(2));

BASS_FXSetParameters throws with
Unhandled exception. System.NotSupportedException: Operation is not supported. (0x80131515)
   at System.StubHelpers.StubHelpers.FmtClassUpdateNativeInternal(Object obj, Byte* pNative, CleanupWorkListElement& pCleanupWorkList)
   at System.StubHelpers.AsAnyMarshaler.ConvertLayoutToNative(Object pManagedHome, Int32 dwFlags)
   at System.StubHelpers.AsAnyMarshaler.ConvertToNative(Object pManagedHome, Int32 dwFlags)
   at Un4seen.Bass.Bass.BASS_FXSetParametersExt(Int32 handle, Object par)
   at Un4seen.Bass.Bass.BASS_FXSetParameters(Int32 handle, Object par)

This doesn't happen for BASS_FX_BFX_ECHO4 type for example. Looking at the source there appears to be additional memory pinning before calling BASS_FXSetParametersExt

Tried with both BASS 2.4.14 and 2.4.15. This works fine when targeting .NET Framework such as net471.

Are there any workarounds for this, or a fix?

EDIT:
Worth clarifying I am using the BASS.NET 'standard' DLL.

radio42

Internally the following is used:
private static extern bool BASS_FXSetParametersExt(int handle, [In][MarshalAs(UnmanagedType.AsAny)] object par);

However, for the BASS_BFX_VOLUME_ENV a special trick must be used in order to support dynamic arrays.
Thus internally an pinned pointer to that array is created using the following code:
hgc = GCHandle.Alloc(pNodes, GCHandleType.Pinned);
ptr = hgc.AddrOfPinnedObject();
So I don't see any reason for .Net Code to complain about this - as all functions should be fully supported.
However, in that past there had been various issues with this kind of marshalling.
Maybe there is still a bug in .NetCode 3.1 ?!

But I am wondering, why you don't use the special .Netcore buikd I am providing?
Please try that to see, if that fixes the issue!

emco

#1533
Is the .NET Standard version able to run on Linux (RaspberryPi with dotnet core 3.1 runtime)?

When running Bass.LoadMe("libbass.so"); I get

Unhandled exception. System.DllNotFoundException: Unable to load shared library 'kernel32.dll' or one of its dependencies. In order to help diagnose loading problems, consider setting the LD_DEBUG environment variable: libkernel32.dll: cannot open shared object file: No such file or directory
   at Un4seen.Bass.Utils.LIBLoadLibrary(String fileName)
   at Un4seen.Bass.Utils.LoadLib(String moduleName, Int32& handle)
   at Un4seen.Bass.Bass.LoadMe(String path)

on linux, shouldnt it look for kernel32.dll.so ?

radio42

Yes, but there is a special .Net core version available which also runs fine on Linux!
But not all internal methods are available/supported on all OSs.
E.g. the LoadMe methods only work on Windows, but is essentially not needed, as each BASS lib is automatically loaded without any special call (even on Windows) when you invoke any method the first time.
Typically you might use e.g. the xxxx_GetVerison method as a first call to load the related lib.
PLugins might be loaded via the BASS_PLuginLoad method respectively.

emco

#1535
Thanks for the help, radio42!
I was able to successfully start my application now. Turns out on raspberrypi you have to use the hardfp version of libbass.so ;)

Unfortunately the sound i get is very distorted. (Tried both the core and the standard dll).
The same code plays fine on a windows machine.

Also a simple C program using just libbass.so plays the same sound fine.

Interestingly once the .NET application has played that distorted sound, all following sounds played on the machine are also distorted, even when played with a completely different applications (i.e. omxplayer). Only a reboot brings back normal sound.

Ian @ un4seen

That sounds strange. Is the problem happening even if you only call BASS_Init + BASS_StreamCreateFile + BASS_ChannelPlay? And are you using PulseAudio or only ALSA? One thing you could try is increasing the output buffer size via the BASS_CONFIG_DEV_BUFFER option (before BASS_Init). The default on Linux is 40ms, so try going up from there.

emco

#1537
Thanks for your answer, Ian.

In the meantime I have tried more things, and infact the BASS_Init call already causes the distorted sound to be played.

Infact any following call to a BASS .NET function changes the frequency of the distortion somehow. It sounds a bit like a late 90s modem dialing up.

The output of Version and Info is:
Bass Version: 2040F00
Speakers=2, MinRate=0, MaxRate=0, DX=0, EAX=False

I am not sure about Pulse or Alsa, but I would assume its Alsa as its a fresh install of raspbian.

Here is my simple code but already the first line causes the distorted sound.

Bass.BASS_Init(-1, 44100, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero);
var stream = Bass.BASS_StreamCreateFile("Data/Sounds/sample.ogg", 0L, 0L, BASSFlag.BASS_DEFAULT);
Bass.BASS_ChannelPlay(stream, false);

The same 3 calls in the C version play fine on the same raspberrypi:

BASS_Init(-1, 44100, 0, NULL, NULL);
HSTREAM stream = BASS_StreamCreateFile(FALSE, "Data/Sounds/sample.ogg", 0, 0, 0);
BASS_ChannelPlay(stream, FALSE);

Ian @ un4seen

I'm not sure how .Net would be affecting the output. Very strange indeed. I will send you a debug BASS version to get more info.

radio42

.Net is not doing anything with this. It behaves exactly like native BASS - except for callbacks where a GC might interrupt things, if not carefully coded.