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.
In ALSA I don't see a way to apply one filter type to more than one channel. My confusion arises because pulse code modulated stereo signals alternately transmit left and right channel data, and it seems wasteful to initiate a separate filter for the left and right halves of a stereo pair. In contrast, with one command line Ecasound seems to apply one filter to stereo pairs.

Internally two filters are run, perhaps/likely in one thread. The interleaved stream is split into two channels which are filtered separately.
 
UPDATE:

Currently testing the plugin that implements various filters...

I have also developed a plugin that simultaneously implements M (e.g. some number of) fractional delay lines using Thiran all-pass filters of order 10 (or so). This was an interesting exercise, and I think I have arrived at novel implementation. Implementing fractional delay for the small (less than 1 or 2 samples) delay that is needed to align the phase between drivers in a loudspeaker crossover can be a bit tricky. I'm thinking about sharing my approach through a short white paper or the like. For now I'm just spreading the news. The fractional delay is used in conjunction with the filters to implement the loudspeaker crossover.
 
Member
Joined 2007
Paid Member
Very interesting update, Charlie!

I have been messing with ALSA and MPD configurations for a while now without success.

@francolargo - defining alsa hw in mpd is the proper way to define a bit perfect playback chain. in order to avoid confusion you can use alsa device alias and use the name eg: hw:X20:0


MPD will only play via ALSA audio_output if "device" specifies an ALSA alias of "type hw". Within such a hardware alias in alsa, I have been unsuccessful at outputting via a slave to anything other than another "type hw" destination (e.g. "hw:0,0"). So, I have been unsuccessful getting MPD data into a type LADSPA block for filtering. However, alsa in this kernel may have 'issues' because I can't get a 'type LADSPA' plugin ('filters' from the list below) to play even using 'aplay':
Code:
root@botic:/data# aplay -f cdr -D filters Track3.aif
Playing raw data 'Track3.aif' : Signed 16 bit Big Endian, Rate 44100 Hz, Stereo
aplay: set_params:1228: Access type not available 

root@botic:/data# aplay -L
null
    Discard all samples (playback) or generate zero samples (capture)
default
filters
clone6
sysdefault:CARD=Botic
    Botic, 
    Default Audio Device
dmix:CARD=Botic,DEV=0
    Botic, 
    Direct sample mixing device
dsnoop:CARD=Botic,DEV=0
    Botic, 
    Direct sample snooping device
hw:CARD=Botic,DEV=0
    Botic, 
    Direct hardware device without any conversions
plughw:CARD=Botic,DEV=0
    Botic, 
    Hardware device with all software conversions

Meanwhile, I will a) see if I can enable ecasound on the BBB, b) run filters with it via command line, and c) implement the MPD 'pipe' output approach. If I can get filtered sound via MPD, then I will worry about the 'bit perfect' aspect!

Cheers!
 
Very interesting update, Charlie!

I have been messing with ALSA and MPD configurations for a while now without success.

MPD will only play via ALSA audio_output if "device" specifies an ALSA alias of "type hw". Within such a hardware alias in alsa, I have been unsuccessful at outputting via a slave to anything other than another "type hw" destination (e.g. "hw:0,0"). So, I have been unsuccessful getting MPD data into a type LADSPA block for filtering. However, alsa in this kernel may have 'issues' because I can't get a 'type LADSPA' plugin ('filters' from the list below) to play even using 'aplay':

Meanwhile, I will a) see if I can enable ecasound on the BBB, b) run filters with it via command line, and c) implement the MPD 'pipe' output approach. If I can get filtered sound via MPD, then I will worry about the 'bit perfect' aspect!

Cheers!

I'm using VLC to play or stream. I set the output of VLC to an ALSA loopback device that I created. That is used as the input to ecasound, and the output of ecasound is the ALSA hardware of the final audio rendering device, in my case it's my onboard audio IC since my motherboard has 8-ch audio out.

I don't use ecasound to actually play files, since it is kind of limited as a player. I run ecasound as a background process from the command line, so it is always "listening" on the ALSA loopback. Then I use VLC to play whatever THRU ecasound to the analog output. Note that VLC can be run from the GUI/desktop or from the command line using cvlc. If you have another player that can output to an ALSA loopback device, this scheme should work for you as well. Piping the output might work just as well, but to me this seems like a bit of a sloppy way to pass data...

I don't have an experience with MPD so I can't help you on that end.
 
Last edited:
Member
Joined 2007
Paid Member
I don't have an experience with MPD so I can't help you on that end.

Thanks for the reply. My rationale for working with MPD is that Volumio uses it. Volumio has features that I would seriously value, and it runs well in stereo with my hardware. Plus, R Taylor got MPD working using a data pipe to ecasound. I'm grinding through Taylor's tutorial now, but I'm a little slow - still low on the learning curve! If/when it works, there is still the matter of hacking Volumio. But there are some good programmers on that project who might implement a LADSPA crossover for fun. :p

Best,

Frank
 
MPD will only play via ALSA audio_output if "device" specifies an ALSA alias of "type hw". Within such a hardware alias in alsa, I have been unsuccessful at outputting via a slave to anything other than another "type hw" destination (e.g. "hw:0,0"). So, I have been unsuccessful getting MPD data into a type LADSPA block for filtering.

Hm, that is weird. Why should MPD accept only hw:X device? Are you sure you defined your additional alsa devices system-wide or for the same user MPD is running under (typically mpd)?
 
Member
Joined 2007
Paid Member
Hm, that is weird. Why should MPD accept only hw:X device? Are you sure you defined your additional alsa devices system-wide or for the same user MPD is running under (typically mpd)?

Thanks for the comment. I run MPD as root, so I am pretty sure I added it to the audio group by: cat /etc/group | grep audio

I would prefer if alsa output worked, when compared to using pipe output.
 
I do not mean being a member of the audio group (root does not have to be in any group, being root it has always access), but defining the alsa devices for a specific user. If mpd runs under root (are you 100% sure?), you have to define the devices in either /root/.asoundrc or /etc/asound.conf.

You can check the actual user of mpd by starting mpd and running command:

Code:
ps axwu | grep mpd
 
Member
Joined 2007
Paid Member
I now have some encouraging results from the Beaglebone using filters in ecasound. I am running three filters: R. Taylor's L/R 4th order lowpass (#9020), R. Taylor's L/R 4th order highpass (#9021), and the CMT 0-.01 sec delay (#1058). I'm running this combination two ways: A) by command line in ecasound, and )B as part of a pipe output configuration using MPD as the player.

The first bit of good news is the CPU load, as measured by TOP:


file type /ecasound alone /ecasound w MPD /MPD w ecasound
44.1kHz - 16 bit 13.6% 12.9% 1%
88.2kHz - 24 bit 27% 13.1% 48%
96kHz - 24 bit 32% 13.5% 59%

With ecasound alone the filters per se only use a third of the CPU even at 96/24. Except at 44.1kHz, MPD demands significant CPU time because the pipe only works when a 44.1 rate is declared.

The second bit of interesting news comes from ecasound's verbose output. Ecasound overrides default sample rates based on header data, so each of the streams to and from the filters was formatted in the native sample rate of the file! :D That is motivation to do everything possible to use an ALSA output from MPD into ecasound. It might just take a ton of trial and error. But the ability to avoid resampling would be huge! I tried removing the -f: specs from the pipe but that stopped any output from ecasound, even though the filters were loading the CPU. Having toiled in vain to get LADSPA filters working directly in ALSA plugins, it is sweet that ecasound doesn't bruise the music and that the same filters work at each different sample rate!

I will tinker with data transfer some more and report back if anything good results. As always, I'm low on the learning curve so ideas and suggestions are a great help.

Cheers,

Frank
 
Member
Joined 2007
Paid Member
You can check the actual user of mpd by starting mpd and running command:

Code:
ps axwu | grep mpd

This is a mess! :p unintelligible to me...

Code:
root@botic:/etc# ps axwu | grep mpd
mpd       1035  0.0  0.2   2784  1408 ?        Ss   07:17   0:03 /usr//ympd -u mpd
upmpdcli  1119  0.1  0.8  81952  4460 ?        Ssl  07:17   0:10 usr/upmpdcli.conf
mpd       1433  5.2 13.3  79440 67864 ?        SLsl 08:15   3:25 sr//etc/mpd.conf
mpd       1480  0.1  0.1   1368   880 ?        S    09:20   0:00 sh -c ecasound... 
mpd       1481 17.5  5.1  27424 26272 ?        SLl  09:20   0:01 ecasound... 
root      1487  0.0  0.1   1604   984 pts/0    S+   09:20   0:00 grep mpd

In this distro there is no .asoundrc - there is a /proc/asound directory containing: Botic card0 cards devices oss pcm timers version
 
Just run the command without the grep filter. You will see a table header on the first line, which tells you the first column is the user under which the process is running.

Code:
pavel@sara:~$ ps axwu
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.0   2812  1564 ?        Ss   08:20   0:00 /sbin/init
root         2  0.0  0.0      0     0 ?        S    08:20   0:00 [kthreadd]
...

Your listing clearly shows your mpd process is running under the mpd user. Are your additional alsa devices defined for the mpd user? My 2 cents the answer is no.

You can put the configuration to system-wide /etc/asound.conf so that every user can see the additional devices. Or put them into .asoundrc saved in mpd user home directory. User directory is listed in /etc/passwd - the argument next to last Understanding /etc/passwd File Format
 
In this distro there is no .asoundrc - there is a /proc/asound directory containing: Botic card0 cards devices oss pcm timers version

/proc/asound is a virtual kernel filesystem for the alsa kernel subsystem. It will give you lots of usefull information for troubleshooting/checking on expected operation. I am talking about /etc/asound.conf or $HOME/.asoundrc files.
 
Member
Joined 2011
Paid Member
I actually had very similar issues as francolargo trying to define and use aliases with alsa and mpd. In my case I was trying to get an EQ integrated into mpd. All instructions referred to .asoundrc files, which did not exist anywhere in my distro. I attempted to make the changes to /etc/asound.conf and that did not work either. Ultimately, I gave up the effort and returned the system to output to hw:device. I was really just trying to see how well it worked, but it still bugs me that I was unsuccessful.
 
All instructions referred to .asoundrc files, which did not exist anywhere in my distro.

This file located in home dir of the user calling the alsa library is not part of the distribution. It is a standard user config, created if required by the user himself.


I attempted to make the changes to /etc/asound.conf and that did not work either. Ultimately, I gave up the effort and returned the system to output to hw:device. I was really just trying to see how well it worked, but it still bugs me that I was unsuccessful.

Linux is no closed-source system, everything is transparent, you just have to know where to look :)

Look:

Code:
pavel@sara:~$ ldd /usr/bin/aplay
	linux-gate.so.1 =>  (0xb787a000)
	librt.so.1 => /lib/tls/i686/cmov/librt.so.1 (0xb7851000)
	libasound.so.2 => /usr/lib/libasound.so.2 (0xb7789000)
	libm.so.6 => /lib/tls/i686/cmov/libm.so.6 (0xb7762000)
	libdl.so.2 => /lib/tls/i686/cmov/libdl.so.2 (0xb775e000)
	libpthread.so.0 => /lib/tls/i686/cmov/libpthread.so.0 (0xb7745000)
	libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0xb75eb000)
	/lib/ld-linux.so.2 (0xb787b000)


pavel@sara:~$ strings /usr/lib/libasound.so.2 | less

Found string:

Code:
ALSA_CONFIG_PATH
/usr/share/alsa/alsa.conf

/usr/share/alsa/alsa.conf says at the very beginning:

Code:
# pre-load the configuration files

@hooks [
        {
                func load
                files [
                        "/usr/share/alsa/pulse.conf"
                        "/usr/share/alsa/bluetooth.conf"
                        "/etc/asound.conf"
                        "~/.asoundrc"
                ]
                errors false
        }
]

These are the config files in my distribution (debian). I would use system-wide /etc/asound.conf or user-specific ~/.asoundrc .

If mpd is running under mpd user and /etc/passwd defines /var/lib/mpd as his home dir (debian default), I would put the specific alsa devices config to /var/lib/mpd/.asoundrc and make sure the file is readable by the mpd user. Or directly to /etc/asound.conf. As we saw in /usr/share/alsa/alsa.conf, both files are handled in the very same way.

That's it, no magic :)
 
Member
Joined 2011
Paid Member
This file located in home dir of the user calling the alsa library is not part of the distribution. It is a standard user config, created if required by the user himself.

I understand that much. After running updatedb and doing a "locate .asoundrc" I found nothing. So I created .asoundrc for myself, root, and mpd (because I wanted to be sure alsa would find it no matter where it went looking) and still, no joy.

Linux is no closed-source system, everything is transparent, you just have to know where to look :)

Look:

Code:
pavel@sara:~$ ldd /usr/bin/aplay
	linux-gate.so.1 =>  (0xb787a000)
	librt.so.1 => /lib/tls/i686/cmov/librt.so.1 (0xb7851000)
	libasound.so.2 => /usr/lib/libasound.so.2 (0xb7789000)
	libm.so.6 => /lib/tls/i686/cmov/libm.so.6 (0xb7762000)
	libdl.so.2 => /lib/tls/i686/cmov/libdl.so.2 (0xb775e000)
	libpthread.so.0 => /lib/tls/i686/cmov/libpthread.so.0 (0xb7745000)
	libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0xb75eb000)
	/lib/ld-linux.so.2 (0xb787b000)


pavel@sara:~$ strings /usr/lib/libasound.so.2 | less

Found string:

Code:
ALSA_CONFIG_PATH
/usr/share/alsa/alsa.conf

/usr/share/alsa/alsa.conf says at the very beginning:

Code:
# pre-load the configuration files

@hooks [
        {
                func load
                files [
                        "/usr/share/alsa/pulse.conf"
                        "/usr/share/alsa/bluetooth.conf"
                        "/etc/asound.conf"
                        "~/.asoundrc"
                ]
                errors false

These are the config files in my distribution (debian). I would use system-wide /etc/asound.conf or user-specific ~/.asoundrc .

If mpd is running under mpd user and /etc/passwd defines /var/lib/mpd as his home dir (debian default), I would put the specific alsa devices config to /var/lib/mpd/.asoundrc and make sure the file is readable by the mpd user. Or directly to /etc/asound.conf. As we saw in /usr/share/alsa/alsa.conf, both files are handled in the very same way.

That's it, no magic :)

That's great if you use debian and the instructions one finds are for debian. In my case, I am using mint and the instructions I found (for various other distros) did not apply at all.

The beginning of my /usr/share/alsa/alsa.conf references both "/etc/asound.conf" and "~/.asoundrc". Since my attempt to create and use .asoundrc failed, I went searching for /etc/asound.conf. It did not exist either, so I created one. Still no joy. (Yes I was restarting alsa each time I made changes and yes the mpd user had read permissions on the files.

The plugin I was attempting to use is "alsaequal", AKA "libasound2-plugin-equal".

But I don't want to waste your time on this. I have wasted enough of my own and I am not too fussed about using an EQ with mpd because I prefer it to be configured for bitperfect playback. Sorry for the OT.
 
Last edited:
Member
Joined 2007
Paid Member
If mpd is running under mpd user and /etc/passwd defines /var/lib/mpd as his home dir (debian default), I would put the specific alsa devices config to /var/lib/mpd/.asoundrc and make sure the file is readable by the mpd user. Or directly to /etc/asound.conf. As we saw in /usr/share/alsa/alsa.conf, both files are handled in the very same way.

According to what I have read, the 'mpd' user is owned by root. The more I study Alsa, the more I am annoyed by its poor documentation. For example, to have ecasound accept an alsa source stream from MPD, it needs one of these syntaxes (on the BBB):
Code:
4. ALSA PCM device, regex: (^alsahw_09$)|(^alsaplugin_09$), params:
... label,card,device,subdevice
5. ALSA named PCM device, regex: ^alsa_09$, params: label,pcm_name
6. JACK interface, regex:
... (^jack$)|(^jack_multi$)|(^jack_alsa$)|(^jack_auto$)|(^jack_generic$),
... params: jack,client,portprefix
7. ALSA PCM device, regex: ^alsahw$, params: label,card,device,subdevice
8. ALSA PCM device, regex: ^alsaplugin$, params:
... label,card,device,subdevice
9. ALSA named PCM device, regex: ^alsa$, params: label,pcm_name

In ALSA I have not been able to create any kind of alias, slave, plug, route, on-and-on... that can act as an MPD output to ecasound, plus be routed separate from the eventual ecasound output. if the signal is not somehow bound to hw:0,0 it ain't playin'. Of course, I'm a noob. Perhaps I will consult the writer of the Botic kernel while we return this very interesting thread to it's regular topic: filters per se. :D
 
I'm definitely having better luck than you, Franco! Maybe you should give up on MPD? I have outlined my setup in this thread, so no need to revisit that here.

Today I implemented a crossover using ecasound and a few instances of my filter plugin. Honestly, the trickiest part was figuring out which ecasound channel went where. I definitely need to come up with a better way to get that sorted out in the future!

Once I was past that hurdle it was smooth sailing. I'm currently enjoying listening to a nice little 2-way active speaker that I built, with the crossover implemented in software with my plugins.

At this point testing of the ACD plugin is complete but I need to come up with a good way to test the fractional delay plugin I wrote. I'm also waiting to be assigned an IDs for the plugins from LADSPA.org headquarters before I release any of this stuff.
 
Member
Joined 2007
Paid Member
I'm definitely having better luck than you, Franco! Maybe you should give up on MPD?

That's excellent, Charlie!

I will say that I'm learning faster all the time! :D However, your comment reminds me that I haven't tried any loopback functions in ALSA yet... I should certainly try that before looking at other players or (gulp) messing with the kernel. That loop function in ecasound certainly is slick!

Overall, its not so bleak here because I have gotten MPD talking to ecasound with a pipe and ecasound's performance and filter execution are very promising. The BBB CPU should be able to run a two-way stereo system at 192kHz. This reassures me that there will be a kick-butt outcome once I get past the fixed frequency restriction of the data pipe. :p

Respecting the adaptive frequency switching of the external system clocks - sourced by the TPA Cronus board - is the secret sauce in this hardware+software recipe. I'm not giving up! ;)

Best,

F.
 
I understand that much. After running updatedb and doing a "locate .asoundrc" I found nothing. So I created .asoundrc for myself, root, and mpd (because I wanted to be sure alsa would find it no matter where it went looking) and still, no joy.

.asoundrc in the user home dir works OK, I have used it many times.


That's great if you use debian and the instructions one finds are for debian. In my case, I am using mint and the instructions I found (for various other distros) did not apply at all.

mint = ubuntu = debian, from alsa POW. The configuration is identical. I am using mint too.

The beginning of my /usr/share/alsa/alsa.conf references both "/etc/asound.conf" and "~/.asoundrc". Since my attempt to create and use .asoundrc failed, I went searching for /etc/asound.conf. It did not exist either, so I created one. Still no joy. (Yes I was restarting alsa each time I made changes and yes the mpd user had read permissions on the files.

Alsa has no process to restart. What you did was reloading alsa kernel modules which are irrelevant for user-space configuration. The libasound library reads the config files on the fly when the audio devices are opened. Just change alsa config files and run your player (whatever one you use, does not pertain to MPD only).
 
According to what I have read, the 'mpd' user is owned by root.

It is irrelevant who owns the player binary file. The config file is read from home directory (~) of the user under which the process is running. Which in your case is mpd, hence /var/lib/mpd.


The more I study Alsa, the more I am annoyed by its poor documentation. For example, to have ecasound accept an alsa source stream from MPD, it needs one of these syntaxes (on the BBB):

Well, that is ecasound configuration, not alsa.

Despite I think this discussion is relevant to LADSPA plugins as they are often configured in alsa directly, I will leave this topic now too. If you want to help with the configuration (which works ok, tested many times by countless people, for MPD too), a new thread will do.
 
Status
This old topic is closed. If you want to reopen this topic, contact a moderator using the "Report Post" button.