LADSPA plugin programming for Linux audio crossovers

Status
This old topic is closed. If you want to reopen this topic, contact a moderator using the "Report Post" button.
Member
Joined 2007
Paid Member
My understanding is that python is used for the ALSA sequencer - i.e. tone generation as with MIDI. Python is on the distro, though I don't know if it is set-up.

I can find NO shared object library with the needed pcm plugins. I wonder if it exists but under different file name(s), or perhaps an incorrect alas-lib configuration is default... Any and all suggestions welcome.
 
Member
Joined 2007
Paid Member
I ran some frequency sweeps and sure enough I've got an lr4 tweeter/woofer crossover.

@Speaky, I'm curious what version of ALSA you are running and on what Linux platform? What do you get when you execute
Code:
 dpkg -l libasound | grep -E "^ii" | tr -s ' ' | cut -d' ' -f3
and from root dir [/]
Code:
 find -iname "*pcm_ladspa*"
I'm starting to wonder if I have uncovered a bug - or perhaps the error message I see is completely misleading.

Today I will start fresh with the Botic Debian kernel and systematically try two ALSA repairs, testing the successful ladspa plug you posted above. I will test it on the older 'stable' distro of ALSA 1.0.27.2 without/with alsa-lib rebuilt from source and possibly on a fresh ALSA 1.0.29 install. Both alsa versions contain 'pcm_ladspa.c', though I see no evidence it gets compiled... :confused:

...not discouraged... :cheers:

Frank
 
Member
Joined 2007
Paid Member
OK, here is a simple two-way crossover in ALSA using the Richard Taylor filters. To correct a fluke in channel routing in the Botic kernel, the output binding numbers in pcm.crosser are reversed between channels 1 and 2. The simple delay plug from the ladspa software development kit is not to my liking, so now I look forward to digging into Charlie's work.
Code:
pcm.!default {
     type plug
     slave.pcm "crosser"
}
ctl.!default {
     type hw
     card 0
}
pcm.crosser {
     type ladspa
     slave.pcm delay
     path "/usr/local/lib/ladspa"    
     channels 4
     plugins
     {
          0 {
               label RTlr4lowpass
               policy none
               input.bindings.0 "Input"
               output.bindings.1 "Output"
               input { controls [ 500 ] }   # 500Hz -3dB XO point
          }
          1 {
               label RTlr4hipass
               policy none
               input.bindings.0 "Input"
               output.bindings.0 "Output"
               input { controls [ 500 ] }
          }
        2 {
               label RTlr4lowpass
               policy none
               input.bindings.1 "Input"
               output.bindings.3 "Output"
               input { controls [ 500 ] }
          }
        3 {
               label RTlr4hipass
               policy none
               input.bindings.1 "Input"
               output.bindings.2 "Output"
               input { controls [ 500 ] }
          }
     }
}
pcm.delay {
     type ladspa
     slave.pcm speaker
     path "/usr/lib/ladspa"    # note different location from above filters
     channels 4
     plugins
     {
        0 {
               label delay_5s
               policy none
               input.bindings.1 "Input"
               output.bindings.1 "Output"
               input { controls [ 0.01 1 ] }    # first param = delay in seconds, second param = ‘wet/dry’
          }
        1 {
               label delay_5s
               policy none
               input.bindings.3 "Input"
               output.bindings.3 "Output"
               input { controls [ 0.01 1 ] }
          }
        2 {
               label delay_5s
               policy none
               input.bindings.0 "Input"
               output.bindings.0 "Output"
               input { controls [ 0 0 ] }
          }
        3 {
               label delay_5s
               policy none
               input.bindings.2 "Input"
               output.bindings.2 "Output"
               input { controls [ 0 0 ] }
          }
     }
}

pcm.speaker {
    type plug
    slave {
     pcm "hw:0,0"
     channels 4
     }
}
Output is not resampled! Example: playing a 96/32 .wav file...
Code:
root@botic:/# cat /proc/asound/Botic/pcm0p/sub0/hw_params
access: MMAP_INTERLEAVED
format: S32_LE
subformat: STD
channels: 4
rate: 96000 (96000/1)
period_size: 1024
buffer_size: 8192

CPU demand on the Beaglebone Black for the above SoX-play task is very reasonable. This is the max CPU load I saw while playing the above 96/32 .wav file (22.7%):

Code:
  PID USER      PR  NI  VIRT  RES  SHR S  %CPU %MEM    TIME+  COMMAND                                                                                                                                                                                                 
 1222 root      20   0 20436  14m 4820 R  22.7  2.9   0:57.53 play                                                                                                                                                                                                    
   46 root      20   0     0    0    0 S   0.3  0.0   0:00.86 mmcqd/0                                                                                                                                                                                                 
  121 root      20   0     0    0    0 S   0.3  0.0   0:00.51 kworker/0:2                                                                                                                                                                                             
 1027 mpd       20   0 79140  73m  26m S   0.3 14.9   0:01.04 mpd                                                                                                                                                                                                     
 1215 root      20   0  8080 3784 3272 S   0.3  0.7   0:01.13 sshd                                                                                                                                                                                                    
 1223 root      20   0  8080 3832 3320 S   0.3  0.8   0:00.30 sshd                                                                                                                                                                                                    
 1229 root      20   0  2672 1812 1408 R   0.3  0.4   0:00.66 top


So now I'm looking forward to investigating your work Charlie! When I finally get everything boxed-up and integrated into the 'big' system, the XO corner freq will be around 150Hz with about a 12msec delay on the woofers. That will all take a while as I now need to learn what the BBB can do for me in terms of a) discretely displaying system status, b) I2C control of volume and DAC operation, c) GPIO to control power relays, d) fan control based on cabinet temp, and e) responding to IR remote control. :rolleyes:

Thanks, all, for the help thus far.

Frank
 
Just a reminder about a possible compilation error. If you are getting an error like this:
Code:
root@botic:/source/ladspa/ACD-plugins# make
g++ -I. -Ofast -Wall -c -fPIC -DPIC -march=native -o ACDf.o ACDf.cpp
cc1plus: error: bad value (native) for -march switch
make: *** [ACDf.o] Error 1
The march=native flag is telling the compiler to find out what hardware the code is being compiled on, and then to tune/optimize it for that hardware. The latest versions of gcc support this command with the "native" option, but I think earlier ones do not, or the hardware is not cooperating with the compiler.

Here are two options for eliminating this error:
  • Edit the Makefile (it's just text) and delete -march=native at the end of the CFLAGS line. Save the Makefile and then try to make again. The error should be gone.
  • Instead of trying to have the compiler figure out what hardware the computer is running on, you can tell it by specifying it with the appropriate march option. If you want the code to be as fast as possible, I suggest that you do a Google search for your EXACT hardware (e.g. BBB, R-Pi, Pentium, etc.) and then look up the correct option in the gcc manpages FOR THE VERSION OF THE GCC COMPILER YOU ARE USING. It takes a couple of minutes fo searching, but if you have come this far grasshopper, I assume you will be curious enough to figure this out as well.
Even if the code is not optimized for speed it will still run just fine even on very modest hardware like the BBB or R-Pi. On my R-Pi 2 I only use 3% CPU for the crossover for a simple 2-way loudspeaker with the march=native compile option removed from CFLAGS (e.g. no optimization).

If you are totally stuck, post here so that everyone can benefit from, and see, the solution.
 
Member
Joined 2007
Paid Member
If you want the code to be as fast as possible, I suggest that you do a Google search for your EXACT hardware (e.g. BBB, R-Pi, Pentium, etc.) and then look up the correct option in the gcc manpages FOR THE VERSION OF THE GCC COMPILER YOU ARE USING. It takes a couple of minutes fo searching, but if you have come this far grasshopper, I assume you will be curious enough to figure this out as well.

LOL!!! :D

I found this source...

For the BBB with gcc 4.6.3-8, I replaced -march=native with:
Code:
 -march=armv7-a -mtune=cortex-a8 -mfloat-abi=hard -mfpu=neon

... worked fine!

For Rpi [2014-06-20-wheezy-raspbian], the same source says:
Code:
 -march=armv6 -mtune=arm1176jzf-s -mfloat-abi=hard -mfpu=vfp
 
For Rpi [2014-06-20-wheezy-raspbian], the same source says:
Code:
 -march=armv6 -mtune=arm1176jzf-s -mfloat-abi=hard -mfpu=vfp

The above is for a Raspberry Pi "1".

The Raspberry Pi 2 has an ARMv7 CPU, so you should use something like this:
Code:
For gcc 4.6 (the default compiler on rasbian)
gcc -march=armv7-a -mfpu=neon-vfpv4 -mfloat-abi=hard 

If you have upgraded gcc on the Pi to 4.8, you can try:
gcc-4.8 -mcpu=cortex-a7 -mfpu=neon-vfpv4 -mfloat-abi=hard
Info taken from this thread:
https://www.raspberrypi.org/forums/viewtopic.php?f=33&t=98354
I readily admit that I haven't tried using the options shown above myself.


.
 
A new version of the ACD plugin package has been uploaded that fixed a couple of minor documentation errors and changed the compile flags to allow the plugins to install on a wider array of systems at the expense of less code optimization. As always, please read all documentation for more detailed info. Current version is 1.02.

The link to the web page where the plugins may be downloaded is found in my signature, below. Please report any bugs or problems using the Email address in the README file.
 
Member
Joined 2007
Paid Member
I have been delayed in investigating the modular IIR filters because the armhf version of MPD (Music Player Daemon) refuses to recognize the alsa configuration defaults. Instead, I have installed the headless player squeezelite. It seems very capable, with numerous web-based controller options! ...and it plays correctly through the ladspa plugins. Plus, Logitech Media Server seems like a strong contender as a server. I like how it synchs with iTunes, which I've used for years as a library manager. In tests with the R.Taylor L-R 4 pole filters, CPU demand was 50-60% w/ 96/32 files. So the Beaglebone system with a two-way crossover is viable in its current form.

Next, attempting to wrangle Charlie's modular filters into alsa... We already know that there will be issues.
 
Frank, we have seen that you are going in a completely different direction from the one that was envisioned when I developed the plugins. Used "as directed" (under ecasound) the ACD plugins are a very effective and efficient way to implement multi-way crossovers. That's is the only LADSPA host that I can endorse at this time.

You might want to consider starting another thread on the theme of "implementing LADSPA plugins using ALSA and the BBB". That way your particular struggles, most of which are not related to my plugins, can be hashed out there, on topic.
 
Member
Joined 2007
Paid Member
I am happy to start a new thread on this! Seeing the modular nature of your filters, I think they will be perfect for ARM-type 'headless' systems. It is fantastic that they are running well in ecasound and that is a great platform, whereas alsa is harder. In that regard, the occasional posts have helped me to stay focused - even though implementation and development are somewhat different. ...will send PM soon...
 
Here is an update on my latest experiments implementing crossovers using ecasound and my "ACD" LADSPA plugin. This time the hardware is a Raspberry Pi 2 running TWO USB stereo DACs.

I had read somewhere that using more than one USB DAC was not going to work on the Pi. I decided that I needed to see for myself since I had a pair of inexpensive 16/48 USB DACs at my disposal. I was happy to discover that, using ecasound and my ACD plugins, I could implement a stereo 2-way loudspeaker crossover on the Pi without any issues. Since these particular USB DACs are very inexpensive but still provide relatively good quality audio I am making plans to use this setup in a pair of active loudspeakers... well, after I have vetted everything for a little while.

I think that the Pi is a great platform for low-cost audio processing when the throughput is not too high, e.g. NOT for high sample rate audio. 48kHz is cheap and effective, just like the R-Pi.
 
Charlie, do the two sound cards stay in sync for long periods? That's the concern, that the clocks don't quite run at the identical frequency, and that one will fall behind the other after several minutes of playing time. Worth testing....

The solution that I've seen offered is to use one as a "master clock", and slave the other one to it.
 
Status
This old topic is closed. If you want to reopen this topic, contact a moderator using the "Report Post" button.