Author Topic: BASS for ARM Linux  (Read 260286 times)

niston

  • Posts: 38
Re: BASS for ARM Linux
« Reply #200 on: 22 Sep '14 - 18:40 »
I did some checking:

Code: [Select]
   var httpInfo = Bass.BASS_ChannelGetTagsHTTP(stream);
    var httpInfo2 = Bass.BASS_ChannelGetTags(stream, BASSTag.BASS_TAG_HTTP);
    if (httpInfo != null) { Console.WriteLine("HTTP Info : " + httpInfo[0].ToString()); }
    if (httpInfo2 != IntPtr.Zero) { Console.Write(Marshal.PtrToStringAnsi(httpInfo2).ToString()); } else { Console.Write("IntPtr.Zero"); }

Output on Windows machine:

Code: [Select]
   HTTP Info : HTTP/1.0 200 OK
    HTTPInfo2 : HTTP/1.0 200 OK

Output on Raspberry Pi:

Code: [Select]
   HTTPInfo2 : IntPtr.Zero

I'm none the wiser.

Full app source is here:
http://niston.wordpress.com/2014/09/20/cross-platform-development/
« Last Edit: 23 Sep '14 - 05:17 by niston »

niston

  • Posts: 38
Re: BASS for ARM Linux
« Reply #201 on: 24 Sep '14 - 14:43 »
Took me a while to convert old VB6 declares to DllImports and hack up enough of a basic c# wrapper for bass.dll to run my experimental code. But I can now confirm that not using BASS.NET doesn't make a difference:

Code: [Select]
   // declare
    [DllImport("bass.dll")]
    internal static extern IntPtr BASS_ChannelGetTags(int handle, TagTypes tags);
    // call
    var result = bassAPI.BASS_ChannelGetTags(stream, bassAPI.TagTypes.BASS_TAG_HTTP);

On my Raspberry Pi, the result is IntPtr.Zero.

I'm running Raspbian 3.12.28+ #712 PREEMPT Tue Sep 16 15:49:13 BST 2014 armv6l GNU/Linux (hardfloat), btw.
« Last Edit: 24 Sep '14 - 20:52 by niston »

niston

  • Posts: 38
Re: BASS for ARM Linux
« Reply #202 on: 26 Sep '14 - 17:10 »
Another issue:

BASS_SetVolume() and BASS_GetVolume() not working on my RPi with USB speakers. Alsamixer can adjust the volume.
Same code has no problem on Windows (USB speakers, too).

Waiting for http://iqaudio.com/?page_id=28 to arrive by Mail so I can test more, and for ARM debug version from Ian :)
« Last Edit: 26 Sep '14 - 17:15 by niston »

niston

  • Posts: 38
Re: BASS for ARM Linux
« Reply #203 on: 28 Sep '14 - 18:44 »
Trying to use Bassmix on hardfloat ARM gives me an instant segfault:

Quote
pi@raspi ~ $ mono sirp.exe
Stacktrace:

  at <unknown> <0xffffffff>
  at sirp.Director..ctor () <0x00037>
  at sirp.Program.Main (string[]) <0x000f3>
  at (wrapper runtime-invoke) <Module>.runtime_invoke_void_object (object,intptr                                                                                                                                                             ,intptr,intptr) <0xffffffff>

Native stacktrace:


Debug info from gdb:

[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/arm-linux-gnueabihf/libthread_db.so.1".
[New Thread 0xb5b7b430 (LWP 5619)]
0xb6ec0a3c in waitpid () from /lib/arm-linux-gnueabihf/libpthread.so.0
  Id   Target Id         Frame
  2    Thread 0xb5b7b430 (LWP 5619) "mono" 0xb6ebe700 in sem_wait@@GLIBC_2.4 ()                                                                                                                                                              from /lib/arm-linux-gnueabihf/libpthread.so.0
* 1    Thread 0xb6f94000 (LWP 5618) "mono" 0xb6ec0a3c in waitpid () from /lib/ar                                                                                                                                                             m-linux-gnueabihf/libpthread.so.0

Thread 2 (Thread 0xb5b7b430 (LWP 5619)):
#0  0xb6ebe700 in sem_wait@@GLIBC_2.4 () from /lib/arm-linux-gnueabihf/libpthrea                                                                                                                                                             d.so.0
#1  0x001fff10 in mono_sem_wait (sem=0x2f523c, alertable=1) at mono-semaphore.c:                                                                                                                                                             119
#2  0x0017db28 in finalizer_thread (unused=<optimized out>) at gc.c:1073
#3  0x001625b4 in start_wrapper_internal (data=0x1b178a8) at threads.c:643
#4  start_wrapper (data=0x1b178a8) at threads.c:688
#5  0x001f5c30 in thread_start_routine (args=0x1ad26b0) at wthreads.c:294
#6  0x00204268 in inner_start_thread (arg=0x1ad26a4) at mono-threads-posix.c:49
#7  0xb6eb7bfc in start_thread () from /lib/arm-linux-gnueabihf/libpthread.so.0
#8  0xb6e24968 in ?? () from /lib/arm-linux-gnueabihf/libc.so.6
#9  0xb6e24968 in ?? () from /lib/arm-linux-gnueabihf/libc.so.6
Backtrace stopped: previous frame identical to this frame (corrupt stack?)

Thread 1 (Thread 0xb6f94000 (LWP 5618)):
#0  0xb6ec0a3c in waitpid () from /lib/arm-linux-gnueabihf/libpthread.so.0
#1  0x000b2148 in mono_handle_native_sigsegv (signal=<optimized out>, ctx=<optim                                                                                                                                                             ized out>) at mini-exceptions.c:2299
#2  0x00027af8 in mono_sigsegv_signal_handler (_dummy=11, info=0xbed4c5d0, conte                                                                                                                                                             xt=0xbed4c650) at mini.c:6777
#3  <signal handler called>
#4  0xb5771f50 in ?? () from /home/pi/libbassmix.so
#5  0xb6f87fc4 in ?? () from /lib/ld-linux-armhf.so.3
#6  0x00000000 in ?? ()

=================================================================
Got a SIGSEGV while executing native code. This usually indicates
a fatal error in the mono runtime or one of the native libraries
used by your application.
=================================================================

Aborted


Error goes away if I remove any calls to Bassmix functions (BASS_Mixer_StreamAddChannel, BASS_Mixer_StreamCreate). When I try with the ARM debug version, I get no logfile - the segfault happens before anything useful can run. The same code works fine on windows, but also segfaults on Arch Linux (gave it a quick try).
« Last Edit: 29 Sep '14 - 09:08 by niston »

Ian @ un4seen

  • Administrator
  • Posts: 24418
Re: BASS for ARM Linux
« Reply #204 on: 29 Sep '14 - 13:42 »
I wonder if that's a library load order issue; I think .Net will only load a library when it is actually used? Are you calling any BASS functions before you call a BASSmix functions? Do you get a crash if you simply do the following?

Code: [Select]
int bassver=Bass.BASS_GetVersion();
int bassmixver=BassMix.BASS_Mixer_GetVersion();

niston

  • Posts: 38
Re: BASS for ARM Linux
« Reply #205 on: 29 Sep '14 - 14:08 »
Hi Ian,

Getting versions doesn't crash:

Quote
Bass Version : 33819168
BassMix Version : 33818370

The application uses StreamCreateURL() to open a Shoutcast stream as decoding channel. This is then plugged into a mixer, and the mixer is being played back. First, I create the mixer stream:

Code: [Select]
_MixerStream = BassMix.BASS_Mixer_StreamCreate(sampleRate, numberOfChannels, BASSFlag.BASS_MIXER_NONSTOP | (FloatingPointSupport ? BASSFlag.BASS_SAMPLE_FLOAT : 0));
Bass.BASS_ChannelPlay(_MixerStream, true);

Then comes StreamCreateURL() and finally, I plug the resulting source channel into the mixer:

Code: [Select]
BassMix.BASS_Mixer_StreamAddChannel(_MixerStream, newStream.Handle, BASSFlag.BASS_MIXER_DOWNMIX | BASSFlag.BASS_STREAM_AUTOFREE | BASSFlag.BASS_MIXER_BUFFER);

If I remove these two BassMix calls, the application starts and connects to the stream (although it can't be heard then because there is no mixer to plug the decoding channel into).
« Last Edit: 29 Sep '14 - 14:27 by niston »

Ian @ un4seen

  • Administrator
  • Posts: 24418
Re: BASS for ARM Linux
« Reply #206 on: 29 Sep '14 - 14:45 »
Which of those 2 BASSmix calls is it crashing in, ie. BASS_Mixer_StreamCreate or BASS_Mixer_StreamAddChannel? If you're unsure, you could try stepping through the code in Mono or write a log file. Also, is it happening on standard Linux too, or only on ARM Linux?

niston

  • Posts: 38
Re: BASS for ARM Linux
« Reply #207 on: 29 Sep '14 - 15:25 »
Unfortunately, no C# code can't be stepped through as it never gets that far; Not even debug log from debug version of Bass library will be written. It appears as if it's not the actual call being executed that crashes, but the simple presence of those calls causing the crash. It seems to crash before having even loaded completely: I can put a Console.WriteLine() as first statement into my Main(), that doesn't execute either.

 ???

Alas, I don't have a Linux box at hand to test; Just a bunch of Raspberry pies.
I could however give you the C# source if that's helpful?

I shall create a small test app that just creates a mixer, to see what happens. Have to leave now, but will be back at it in a few hours.
« Last Edit: 29 Sep '14 - 15:38 by niston »

Ian @ un4seen

  • Administrator
  • Posts: 24418
Re: BASS for ARM Linux
« Reply #208 on: 29 Sep '14 - 16:06 »
Is it possible that the libbassmix.so file is the wrong version, eg. softfp instead of hardfp? If that's not it, does Mono have a way to define the load order of native libraries, and if so, is BASS loaded before BASSmix? If a log file isn't written when using the debug BASS version, then it seems like BASSmix is getting loaded before BASS is.

niston

  • Posts: 38
Re: BASS for ARM Linux
« Reply #209 on: 29 Sep '14 - 21:40 »
Is it possible that the libbassmix.so file is the wrong version, eg. softfp instead of hardfp?

I thought of that too, but I deleted all .so and replaced them with hardfp versions from bass24-linux-arm.zip. So, unless there's a wrong version in that archive, this shouldn't be the problem. I also tried with softfp versions just to make sure. It couldn't find libs then, as expected.

Quote
If that's not it, does Mono have a way to define the load order of native libraries, and if so, is BASS loaded before BASSmix? If a log file isn't written when using the debug BASS version, then it seems like BASSmix is getting loaded before BASS is.

I wouldn't know if such a mechanism exists, a quick web search returned nothing useful. At least according to my code, it seems unreasonable that bassmix should get loaded before bass:

Code: [Select]
       public Streamer(int sampleRate, int numberOfChannels, int maxNumberOfStreams)
        {
            // our streams
            _Streams = new List<InetStream>();
            MaximumStreams = maxNumberOfStreams;            

            // BASS setup / init
            SetupBassLibrary();
            InitBassLibrary();

            // this is the output mixer
            _MixerStream = BassMix.BASS_Mixer_StreamCreate(sampleRate, numberOfChannels, BASSFlag.BASS_MIXER_NONSTOP | (FloatingPointSupport ? BASSFlag.BASS_SAMPLE_FLOAT : 0));

            // enable level meter update
            _LevelsUpdate.Elapsed += _LevelsUpdate_Elapsed;
            _LevelsUpdate.Interval = 250;
            _LevelsUpdate.Start();

            // play back the output channel to the default audio device
            Bass.BASS_ChannelPlay(_MixerStream, true);
        }

and further:

Code: [Select]
       private void SetupBassLibrary()
        {
            // we must register BASS.NET to be able to run in console, otherwise will crash on Unix without X Server
            //BassNet.Registration("<email>", "<regkey>"); // get a freeware key by registering on http://bass.radio42.com/

            // System specific path separator
            var dirSep = System.IO.Path.DirectorySeparatorChar;

            // load BASS plugins from current directory
            Bass.BASS_PluginLoadDirectory(Environment.CurrentDirectory);
            
            // load BASS plugins from codecs subdirectory
            Bass.BASS_PluginLoadDirectory(Environment.CurrentDirectory + dirSep + "codecs" + dirSep);

            
            // set BASS configuration
            Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_NET_READTIMEOUT, 20000);             // network read timeout 20000ms
            Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_NET_BUFFER, 10000);                  // network buffer size 10000ms
            Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_NET_PREBUF, 30);                     // prebuffer 30% of buffer size
            Bass.BASS_SetConfig(BASSConfig.BASS_CONFIG_NET_PLAYLIST, true);                 // enable playlist processing
        }

        private void InitBassLibrary(int deviceID = -1)
        {
            if (Bass.BASS_Init(deviceID, 44100, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero))
            {
                this.FloatingPointSupport = CheckFloatSupport();
            }
            else
            {
                this.FloatingPointSupport = false;
                throw new Exception("BASS_Init failed (" + Bass.BASS_ErrorGetCode().ToString() + ").");
            }
        }

But then again, I think you are referring to the order in which mono loads the involved native libs. Which has most likely absolutely nothing to do with the order in which I'm calling any functions in my code...  ;D

Now discussing the issue on #mono@irc.gnome.org, but the guy to talk to is currently not around. What the others there had to say so far:

Quote
<directhex> you're 101% certain that these libbass.so binaries are for armv6, not armv7?

Well I can tell by experience that libbass.so itself works fine on armv6. And I believe that there wouldn't be a chance that the libbassmix.so was accidentally built for v7 instead of v6. Right, Ian?
« Last Edit: 30 Sep '14 - 15:50 by niston »

niston

  • Posts: 38
Re: BASS for ARM Linux
« Reply #210 on: 30 Sep '14 - 00:20 »
I did write the test program I spoke of earlier.
Very simple: Init BASS-Create mixer stream-play the stream back-wait for key-stop mixer stream-free BASS.

Complete source code is here: http://pastebin.com/Fnw7qxw8.

Program works on Windows and prints the mixer handle.
On Raspberry Pi SIGSEGV: http://pastebin.com/y0NNjpVW.

It would be helpful if someone could implement above test for libbassmix.so on the Raspberry in native C,  without mono involved. Anyone?
« Last Edit: 30 Sep '14 - 15:51 by niston »

Ian @ un4seen

  • Administrator
  • Posts: 24418
Re: BASS for ARM Linux
« Reply #211 on: 30 Sep '14 - 16:43 »
I tried implementing your test in C without the SetupBassLibrary part (that's BASS.Net specific), and it's working fine. To confirm whether it's the SetupBassLibrary stuff that's causing the problem, what happens if you remove it, in particular the BASS_PluginLoadDirectory call?

niston

  • Posts: 38
Re: BASS for ARM Linux
« Reply #212 on: 30 Sep '14 - 16:46 »
I rewrote it:

Code: [Select]
 //Bass.BASS_PluginLoadDirectory(Environment.CurrentDirectory);
  Bass.BASS_PluginLoad("bassmix.dll");

Still segfaults on the Pi. So it's down to mono I guess?

Btw: Can't remove the BassNet.Registration() call. Else will crash on the Berry because I don't run X.
« Last Edit: 30 Sep '14 - 16:50 by niston »

Ian @ un4seen

  • Administrator
  • Posts: 24418
Re: BASS for ARM Linux
« Reply #213 on: 30 Sep '14 - 16:54 »
What about if you don't even call BASS_PluginLoad? Note that it will fail to load BASSmix anyway, as it is only for add-ons that add support for additional file formats, eg. BASSFLAC/WV/etc.

niston

  • Posts: 38
Re: BASS for ARM Linux
« Reply #214 on: 30 Sep '14 - 17:21 »
Will try this right away. In the mean time, I managed to get gdb to cooperate as per http://www.mono-project.com/docs/debug+profile/debug/#debugging-with-gdb. It looks like this:

Quote
pi@raspi ~ $ gdb --args mono sirp.exe
GNU gdb (GDB) 7.4.1-debian
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "arm-linux-gnueabihf".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /usr/bin/mono...done.
(gdb) r
Starting program: /usr/bin/mono sirp.exe
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/arm-linux-gnueabihf/libthread_db.so.1".
[New Thread 0xb5bf7430 (LWP 2967)]

Program received signal SIGSEGV, Segmentation fault.
0xb5889f50 in ?? () from /home/pi/libbassmix.so
(gdb) bt
#0  0xb5889f50 in ?? () from /home/pi/libbassmix.so
#1  0xb6fecfc4 in ?? () from /lib/ld-linux-armhf.so.3
#2  0x00000000 in ?? ()
(gdb)
« Last Edit: 30 Sep '14 - 17:32 by niston »

niston

  • Posts: 38
Re: BASS for ARM Linux
« Reply #215 on: 30 Sep '14 - 17:25 »
It still segfaults even without the PluginLoad() call.

Ian @ un4seen

  • Administrator
  • Posts: 24418
Re: BASS for ARM Linux
« Reply #216 on: 30 Sep '14 - 17:42 »
Program received signal SIGSEGV, Segmentation fault.
0xb5889f50 in ?? () from /home/pi/libbassmix.so
(gdb) bt
#0  0xb5889f50 in ?? () from /home/pi/libbassmix.so
#1  0xb6fecfc4 in ?? () from /lib/ld-linux-armhf.so.3
#2  0x00000000 in ?? ()
(gdb)

What do get if you type "info sharedlibrary libbassmix.so" at that point?

niston

  • Posts: 38
Re: BASS for ARM Linux
« Reply #217 on: 30 Sep '14 - 17:47 »
Quote
(gdb) info sharedlibrary libbassmix.so
From        To          Syms Read   Shared Object Library
0xb58835e0  0xb588c328  Yes (*)     /home/pi/libbassmix.so
(*): Shared library is missing debugging information.
(gdb)

niston

  • Posts: 38
Re: BASS for ARM Linux
« Reply #218 on: 30 Sep '14 - 18:00 »
Useless without symbols:

Quote
(gdb) info registers
r0             0xe      14
r1             0xb5a61538       3047560504
r2             0x1247c  74876
r3             0x0      0
r4             0x2      2
r5             0x1      1
r6             0x379350 3642192
r7             0x0      0
r8             0xd      13
r9             0xbeffeba4       3204443044
r10            0xb5a61480       3047560320
r11            0xbeffec54       3204443220
r12            0xbeffebc8       3204443080
sp             0xbeffeb60       0xbeffeb60
lr             0xb6fecfc4       -1224814652
pc             0xb5a56f50       0xb5a56f50
cpsr           0x60000010       1610612752
(gdb) info frame
Stack level 0, frame at 0xbeffeb60:
 pc = 0xb5a56f50; saved pc 0xb6fecfc4
 called by frame at 0xbeffebb0
 Arglist at 0xbeffeb60, args:
 Locals at 0xbeffeb60, Previous frame's sp is 0xbeffeb60
(gdb)
« Last Edit: 30 Sep '14 - 18:04 by niston »

niston

  • Posts: 38
Re: BASS for ARM Linux
« Reply #219 on: 30 Sep '14 - 19:21 »
Did a --trace=all on the test program (Thanks, shana :), the output is here: http://pastebin.com/9nBx1dDe. Trace of empty.exe (has *nothing* in it) as a reference: http://pastebin.com/CMGbKtPL


Btw Ian, did you test the native C app on hardfloat?
« Last Edit: 30 Sep '14 - 20:04 by niston »

Ian @ un4seen

  • Administrator
  • Posts: 24418
Re: BASS for ARM Linux
« Reply #220 on: 1 Oct '14 - 13:55 »
(gdb) info sharedlibrary libbassmix.so
From        To          Syms Read   Shared Object Library
0xb58835e0  0xb588c328  Yes (*)     /home/pi/libbassmix.so
(*): Shared library is missing debugging information.
(gdb)

From that and the crash address, it appears to have crashed in the BASSmix library's destructor function, which gets called before the library is unloaded. So it looks like BASSmix was in the process of getting unloaded, even though your app has only just been launched? One possible explanation for that is if BASS_PluginLoad was called on the BASSmix library, as BASS_PluginLoad would unload it after seeing that it can't be plugged into the stream/sample creation functions. Do you get the exact same crash (ie. at same address) after removing the BASS_PluginLoadDirectory/BASS_PluginLoad call? I tried adding a BASS_PluginLoad("libbassmix.so") call to the C version of the test, and it didn't crash, so even if you are calling that, I'm not sure it would explain the crash.

To help confirm the crash location, please also type "x/5i $pc" in GDB and post the output. Also try "info sharedlibrary libbass.so", ie. does that show the BASS library loaded?

Btw Ian, did you test the native C app on hardfloat?

Yep, I'm testing on a hardfp distro (Pidora).

niston

  • Posts: 38
Re: BASS for ARM Linux
« Reply #221 on: 1 Oct '14 - 14:39 »
[...] Do you get the exact same crash (ie. at same address) after removing the BASS_PluginLoadDirectory/BASS_PluginLoad call?
Yes, exact same address.

Quote
To help confirm the crash location, please also type "x/5i $pc" in GDB and post the output.

The output:
Code: [Select]
(gdb) x/5i $pc
=> 0xb5a56f50:  ldr     r3, [r3, #4]
   0xb5a56f54:  ldr     r0, [pc, #288]  ; 0xb5a5707c
   0xb5a56f58:  add     r0, pc, r0
   0xb5a56f5c:  mov     r1, #1
   0xb5a56f60:  blx     r3

Quote
Also try "info sharedlibrary libbass.so", ie. does that show the BASS library loaded?

Code: [Select]
(gdb) info sharedlibrary libbass.so
No shared libraries matched.

Ian @ un4seen

  • Administrator
  • Posts: 24418
Re: BASS for ARM Linux
« Reply #222 on: 1 Oct '14 - 15:51 »
Code: [Select]
(gdb) x/5i $pc
=> 0xb5a56f50:  ldr     r3, [r3, #4]
   0xb5a56f54:  ldr     r0, [pc, #288]  ; 0xb5a5707c
   0xb5a56f58:  add     r0, pc, r0
   0xb5a56f5c:  mov     r1, #1
   0xb5a56f60:  blx     r3

OK. That shows that it is actually crashing in the BASSmix library's constructor function (called when the library is loaded), which makes more sense.

Code: [Select]
(gdb) info sharedlibrary libbass.so
No shared libraries matched.

Yep, this confirms that the BASS library isn't loaded, which is no doubt what's causing the crash. Need to somehow get BASS loaded before BASSmix is. What about if you call BASS_GetVersion first thing in your code?

niston

  • Posts: 38
Re: BASS for ARM Linux
« Reply #223 on: 2 Oct '14 - 00:43 »
[...] this confirms that the BASS library isn't loaded, which is no doubt what's causing the crash.

Yes, I agree.

Quote
Need to somehow get BASS loaded before BASSmix is. What about if you call BASS_GetVersion first thing in your code?

Ok, I have found that this works:

Code: [Select]
           // this is the output mixer
            Console.WriteLine(Bass.BASS_GetVersion().ToString());
            _MixerStream = BassMix.BASS_Mixer_StreamCreate(sampleRate, numberOfChannels, BASSFlag.BASS_MIXER_NONSTOP | (FloatingPointSupport ? BASSFlag.BASS_SAMPLE_FLOAT : 0));

If the Console.WriteLine() stuff is placed earlier in code, it won't work. If it's placed right before Mixer_StreamCreate() it works.  ???

Maybe it has to with my Bass.BASS_Init() etc being in a function? Because I placed the GetVersion() right after the Init() and it wouldn't work. The only difference I can think of is that all my Init stuff is in a function and not straight in line with the above code. Pure speculation is what it is.

Will talk to the mono guys and, perhaps, investigate further. But anyways, libbassmix.so and mono are cooperative now and you are my hero, Ian! Most excellent support here!  :D
« Last Edit: 2 Oct '14 - 05:05 by niston »

niston

  • Posts: 38
Re: BASS for ARM Linux
« Reply #224 on: 2 Oct '14 - 03:30 »