• Disclaimer: This Vendor's Forum is a paid-for commercial area. Unlike the rest of diyAudio, the Vendor has complete control of what may or may not be posted in this forum. If you wish to discuss technical matters outside the bounds of what is permitted by the Vendor, please use the non-commercial areas of diyAudio to do so.

LADSPA filters for digital crossovers on the BBB

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
OK, looks like progress... Regarding your asound.conf structure, you should audit the signal flow through the user space.

The final output to hardware is "hw:0,0". Which plugs send sound there? Both pcm.filter1 and pcm.plugequal. There is no other input into pcm.filter1 so if you send program output directly to that plug (and the plug works), then sound should only incorporate the shelf filter and no other functions. As is, there is no chain of plugs that will run both the filter and the equalizer. While talking about pcm.filter1, I see that the path to the LADSPA filters is the one I use, not the one I suggested you change to. Just be sure that the entire path to *your* ACDf filter set is in that 'path' line of filter1.

Now back to the chain of events. If you input audio into pcm.equal, it is then sent to pcm.plugequal (listed as the 'slave'). ...and that only goes to hardware out - hw:0,0. So if you want both the shelf filter and the equalizer to work, you need to change some 'slave' (output) designations. I suggest input into pcm.default and slave that to pcm.filter1. Then, slave pcm.filter1 to pcm.equal. That will give you a type-plug as the input and output of the type-LADSPA filter1 plug (which in my experience helps). ...and we know that the type-equal plug works as the output to hw:0,0. Is that sufficiently unclear? :)

Summary: do three things. 1) correct the plugin path to your ACDf filter set [/usr/local/lib/ladspa?] 2) correct the 'slave' lines to give a single signal path: pcm!default -> pcm.filter1 -> pcm.equal -> pcm.plugequal -> hw:0,0 [double check after your edits by executing 'aplay -L'] 3) send mpd or other program output to either plug:default, or plug:filter1.

I think you're close...

Frank
 
I got it (well something) working.... :)

I found this.... from an instructable...
https://github.com/jrubinstein/raspiDSP/blob/master/alsa configuration asoundrc-experimental2.cpp

Raspberry Pi Music Server with Built-in Crossover and DSP - 6

I decided to distill the config to the simplest ACDf invokation and with no other distractions. A low pass at 200hz.

Code:
pcm.!default {
     type plug
     slave.pcm filter1
}

ctl.!default {
     type hw
     card 0
}

pcm.filter1 {
     type ladspa
     slave.pcm speaker
     path "/usr/local/lib/ladspa"  # must indicate filter directory
     channels 2                    # two is default, other channel counts must be specified
     plugins
     {
          0 {        # must start with zero and not skip numbers in sequence
               label ACDf     # you could instead use the filter id number
               policy none
               input.bindings.0 "Input"     #input to filter is channel 0
               output.bindings.0 "Output"  #output from filter is channel 0
               input { controls [1 1 -6 200] }   # simple LP to start with
          }
          1 {
               label ACDf
               policy none
               input.bindings.1 "Input"
               output.bindings.1 "Output"
               input { controls [1 1 -6 200] }
          }
     }
}

pcm.speaker {
    type plug
    slave {
     pcm "hw:0,0"
     channels 2
     rate "unchanged"
    }
}

pcm.plughw.slave.rate = "unchanged";

Running speaker-test with -D of default or plug:filter1 results in output and filtering.
Running speaker-test direct to HW:0,0 produces obviously different sound (more frequencies).

Now to figure out how to get the shelf filter working.

J.
 
Anyway, after all of that, I think this is what you want:
Code:
input { controls [25 0 -4 740 0 0 0] }   # high shelf 740Hz, -4dB
Actually I was wrong when I made that suggestion. Because of the way the second order shelving filters are now implemented (in ACDf ver 2) you need to provide the Qp value whereas before it was fixed at 0.707 and you could supply a value of "0" for that parameter. So, it should be like this:
Code:
input { controls [25 0 -4 740 0.7 0 0] }   # high shelf 740Hz, -4dB

See THIS POST for more info.
 
Last edited:
Hi,

I've been fooling around with the new ACD 2.0 plugins on a Raspbery Pi 3 + Debian Jessie minimal, implemented as ALSA plugins, and to my big surprise (I'm such a computer idiot....) I got it running with a cheapo usb soundcard. Thanks to Charlie for this marvellous piece of software, and Frank for getting me started in the first place by his tutorial and incredible perseverance in that matter, and all the others who contributed!

I was now wondering how to set things up for developing and testing a speaker with this crossover with, say, ARTA. My usual setup is:

measurement computer with ARTA -> soundcard out -> MiniDSP 2x4-> multichannel amplifier -> speaker under test (SUT?) -> calibrated microphone -> soundcard Mic in -> measurement computer with ARTA

A wonderful and easy way to develop those active speakers ;-)

I now would like to replace MiniDSP with Raspberry Pi + ACD in the above chain, so, the way I see it, I have to find a way to pipe the output of the measurement computer soundcard via Raspi USB Soundcard line-in to the ALSA plugins and to the amplifiers feeding the speaker, right? How, considering my noob-ness with Linux, is this possible? A Google scan turned up arecord|aplay, but I was wondering if you computer cracks had a different/better/easier way to set things up?

Thanks, and best regards!

hallodeletue
 
Member
Joined 2007
Paid Member
I was now wondering how to set things up for developing and testing a speaker with this crossover with, say, ARTA. My usual setup is:

measurement computer with ARTA -> soundcard out -> MiniDSP 2x4-> multichannel amplifier -> speaker under test (SUT?) -> calibrated microphone -> soundcard Mic in -> measurement computer with ARTA

A wonderful and easy way to develop those active speakers ;-)

I now would like to replace MiniDSP with Raspberry Pi + ACD in the above chain, so, the way I see it, I have to find a way to pipe the output of the measurement computer soundcard via Raspi USB Soundcard line-in to the ALSA plugins and to the amplifiers feeding the speaker, right? How, considering my noob-ness with Linux, is this possible? A Google scan turned up arecord|aplay, but I was wondering if you computer cracks had a different/better/easier way to set things up?

Thanks, and best regards!

hallodeletue

Greetings @hallodeletue,

I'm happy to read of your success! There was a question over on the ACDf thread just yesterday. This link goes there.

Charlie mentioned two USB interfaces for analog signals. My personal solution uses a different converter to adapt from SPDIF to USB. With that, I send frequency sweep output to the linux board over Apple's AirPlay using the same AppleTV that provides video to the system.

As more people do what you are doing, it will be interesting to learn from them and probe the limits of the ARMhf platforms.
 
I got it (well something) working.... :)

I found this.... from an instructable...
https://github.com/jrubinstein/raspiDSP/blob/master/alsa configuration asoundrc-experimental2.cpp

Raspberry Pi Music Server with Built-in Crossover and DSP - 6

I decided to distill the config to the simplest ACDf invokation and with no other distractions. A low pass at 200hz.

Code:
pcm.!default {
     type plug
     slave.pcm filter1
}

ctl.!default {
     type hw
     card 0
}

pcm.filter1 {
     type ladspa
     slave.pcm speaker
     path "/usr/local/lib/ladspa"  # must indicate filter directory
     channels 2                    # two is default, other channel counts must be specified
     plugins
     {
          0 {        # must start with zero and not skip numbers in sequence
               label ACDf     # you could instead use the filter id number
               policy none
               input.bindings.0 "Input"     #input to filter is channel 0
               output.bindings.0 "Output"  #output from filter is channel 0
               input { controls [1 1 -6 200] }   # simple LP to start with
          }
          1 {
               label ACDf
               policy none
               input.bindings.1 "Input"
               output.bindings.1 "Output"
               input { controls [1 1 -6 200] }
          }
     }
}

pcm.speaker {
    type plug
    slave {
     pcm "hw:0,0"
     channels 2
     rate "unchanged"
    }
}

pcm.plughw.slave.rate = "unchanged";

Running speaker-test with -D of default or plug:filter1 results in output and filtering.
Running speaker-test direct to HW:0,0 produces obviously different sound (more frequencies).

Now to figure out how to get the shelf filter working.

J.

Hi, I tried implementing this but systematically get this error:
ALSA lib pcm_ladspa.c:1362:(snd_pcm_ladspa_parse_bindings) Unable to find an audio port (output.bindings.0) for channel 0

Does anyone know how to solve it ?
 
Managed to get it to work, finally... It takes time to figure out the logic and syntax.

Here is what I did for a simple 2-way crossover (vertical bi-amp, left channel is sent to one amp, right channel to another).


Code:
pcm.!default {
    type route
    ttable.0.0 1
    ttable.1.2 1
    ttable.1.3 1
    ttable.0.1 1
    type plug
    slave.pcm crossover
}
ctl.!default {
     type hw
     card D20
}

pcm.crossover {
     type ladspa
     slave.pcm speaker
     path "/usr/lib/ladspa"
     channels 4
     plugins
     {
          0{
               label RTlr4lowpass
               policy none
               input.bindings.0 "Input"
               output.bindings.0 "Output"
               input { controls [2000] }
          }
          1 {
                label RTlr4hipass
                policy none
                input.bindings.1 "Input"
                output.bindings.1 "Output"
                input { controls [2000] }
          }
          2 {
                label RTlr4lowpass
                policy none
                input.bindings.2 "Input"
                output.bindings.2 "Output"
                input { controls [2000] }
          }
          3 {
                label RTlr4hipass
                policy none
                input.bindings.3 "Input"
                output.bindings.3 "Output"
                input { controls [2000] }
          }
      }
}

pcm.speaker {
    type plug
    slave.pcm "surround41:D20
}

Am using this on an Alix 3D2 board with a multichannel USB->I2S card from DIYINHK. Seems to be working !
 
Last edited:
Member
Joined 2007
Paid Member
Managed to get it to work, finally... It takes time to figure out the logic and syntax.

Here is what I did for a simple 2-way crossover (vertical bi-amp, left channel is sent to one amp, right channel to another).


Code:
pcm.!default {
    type route
    ttable.0.0 1
    ttable.1.2 1
    ttable.1.3 1
    ttable.0.1 1
    type plug
    slave.pcm crossover
}
ctl.!default {
     type hw
     card D20
}

pcm.crossover {
     type ladspa
     slave.pcm speaker
     path "/usr/lib/ladspa"
     channels 4
     plugins
     {
          0{
               label RTlr4lowpass
               policy none
               input.bindings.0 "Input"
               output.bindings.0 "Output"
               input { controls [2000] }
          }
          1 {
                label RTlr4hipass
                policy none
                input.bindings.1 "Input"
                output.bindings.1 "Output"
                input { controls [2000] }
          }
          2 {
                label RTlr4lowpass
                policy none
                input.bindings.2 "Input"
                output.bindings.2 "Output"
                input { controls [2000] }
          }
          3 {
                label RTlr4hipass
                policy none
                input.bindings.3 "Input"
                output.bindings.3 "Output"
                input { controls [2000] }
          }
      }
}

pcm.speaker {
    type plug
    slave.pcm "surround41:D20
}

Am using this on an Alix 3D2 board with a multichannel USB->I2S card from DIYINHK. Seems to be working !

I have not seen this error and it may be specific to your hardware. However, I am unsure that your t.table results in proper stereo because before filtering you are routing 0->1 and 1->2 plus 1->3. Are channels 2 and 3 getting a different signal than 0?

Within each filter you can route the signal using input and output bindings. For example, within a filter this will 'copy' the contents of channel 0, filter it, and send the result to channel 2.
input.bindings.0 "Input"
output.bindings.2 "Output"

The following should maintain separation between left and right signals and make the t.table unnecessary. This will result in 0 + 2 = left, 1 + 3 = right. If needed you can change the filter applied in each of the four positions or you can add a type-route plug at the end so that the four distinct channels reach their desired destination. But I wouldn't send 0->1 until after all the filters have run.

Code:
pcm.crossover {
     type ladspa
     slave.pcm speaker
     path "/usr/lib/ladspa"
     channels 4
     plugins
     {
          0{
               label RTlr4lowpass
               policy none
               input.bindings.0 "Input"
               output.bindings.2 "Output"
               input { controls [2000] }
          }
          1 {
                label RTlr4hipass
                policy none
                input.bindings.0 "Input"
                output.bindings.0 "Output"
                input { controls [2000] }
          }
          2 {
                label RTlr4lowpass
                policy none
                input.bindings.1 "Input"
                output.bindings.3 "Output"
                input { controls [2000] }
          }
          3 {
                label RTlr4hipass
                policy none
                input.bindings.1 "Input"
                output.bindings.1 "Output"
                input { controls [2000] }
          }
      }
}

Cheers,

Frank
 
Member
Joined 2007
Paid Member
CPU usage running squeezelite on th Alix 3D2 board (meager 500 MHz AMD Geode LX800) is around 30%. Now I have to play around with the frquency/filter settings to fine tune it.

I would also like to use Airplay, through Shairport-sync. I understand this is only possible through ecasound ?

What operating system? I would expect the crossover to work as long as the Shairport-sync is working. I have no direct experience with this software because I use SPDI/F output from an AppleTV to process the audio portion of video in addition to music alone. Your ALSA crossover will automatically filter anything sent to 'default'.
 
Last edited:
I have not seen this error and it may be specific to your hardware.

It must have been just a syntax error, as I no longer have the issue.


However, I am unsure that your t.table results in proper stereo because before filtering you are routing 0->1 and 1->2 plus 1->3. Are channels 2 and 3 getting a different signal than 0?

I believe it works, as I checked with the 4 channel wav file that spells out the diferent channels - but I will double check.

The documentation on these alsa statements is really poor...

Thanks for your reply and pointers.
 
Last edited:
What operating system? I would expect the crossover to work as long as the Shairport-sync is working. I have no direct experience with this software because I use SPDI/F output from an AppleTV to process the audio portion of video in addition to music alone. Your ALSA crossover will automatically filter anything sent to 'default'.

I am using debian. I tried shairport-sync with "default" but it does not work. I read somewhere why, and will try to find the link.

I am pretty happy to have gotten this far - I find this software crossover solution "elegant". Will also check out ecasound.
 
Last edited:
Member
Joined 2007
Paid Member
I am using debian. I tried shairport-sync with "default" but it does not work. I read somewhere why, and will try to find the link.

The syntax for alsa-related program output is rather variable and, like a lot of ALSA, poorly documented. You might try:
'plug:default'
'alsa plug:default'
I am pretty happy to have gotten this far - I find this software crossover solution "elegant". Will also check out ecasound.
Ecasound is good if your sample rate does not vary, otherwise it will resample to the pre-selected frequency. ALSA will adapt to different sample rates of the output without resampling. I can also recommend the ACDf filter set - it sounds better in my system than the Richard Taylor filters. ...more options to customize.
 
Last edited:
The syntax for alsa-related program output is rather variable and, like a lot of ALSA, poorly documented. You might try:
'plug:default'
'alsa plug:default'

Ecasound is good if your sample rate does not vary, otherwise it will resample to the pre-selected frequency. ALSA will adapt to different sample rates of the output without resampling. I can also recommend the ACDf filter set - it sounds better in my system than the Richard Taylor filters. ...more options to customize.

Does not work either with those devices. I found the link (see the last comment): https://github.com/mikebrady/shairport-sync/issues/212
It seems fairly straightforward:

shairport-sync -v -c /etc/shairport-sync.conf -- -dplug:filters

But what to put in /etc/shairport-sync.conf in that case ?

I will definitely try out the ACDF filter set. Thanks again. I am quite new to this topic (crossovers). Its fun to work on !
 
Last edited:
Member
Joined 2007
Paid Member
Does not work either with those devices. I found the link (see the last comment): https://github.com/mikebrady/shairport-sync/issues/212
It seems fairly straightforward:

shairport-sync -v -c /etc/shairport-sync.conf -- -dplug:filters

But what to put in /etc/shairport-sync.conf in that case ?

I will definitely try out the ACDF filter set. Thanks again.

The '-d' option looks like the output specification. You want to use the plug 'default', not 'filters'. Also, "-dplug:filters" has suspicious syntax. Perhaps "-d plug:default" might work? [Note the space after '-d']

Again, I have no experience with Shairport. I can't help you with /etc/shairport-sync.conf. Note that the output 'hw:0' or 'hw:0,0' (if you happen across it) will avoid your ALSA crossover. You should output to 'plug:default' or something like it... Sorry I have no answers beyond that.

In the comment you listed, the first option used a 'pipe' [this symbol - '|'] to send the output of shairport to the command 'aplay' and that command specified the output using the '-D' option. That is not an elegant solution - the 'aplay' process will degrade the synchronization. Also, '-D' (capital D) only specifies the output for 'aplay' and 'speaker-test'. That option is case sensitive...
 
Last edited:
The '-d' option looks like the output specification. You want to use the plug 'default', not 'filters'. Also, "-dplug:filters" has suspicious syntax. Perhaps "-d plug:default" might work? [Note the space after '-d']

Again, I have no experience with Shairport. I can't help you with /etc/shairport-sync.conf. Note that the output 'hw:0' or 'hw:0,0' (if you happen across it) will avoid your ALSA crossover. You should output to 'plug:default' or something like it... Sorry I have no answers beyond that.

In the comment you listed, the first option used a 'pipe' [this symbol - '|'] to send the output of shairport to the command 'aplay' and that command specified the output using the '-D' option. That is not an elegant solution - the 'aplay' process will degrade the synchronization. Also, '-D' (capital D) only specifies the output for 'aplay' and 'speaker-test'. That option is case sensitive...

Thanks again. Will investigate and update when I get it working (I feel confident). My primary use is Roon to Squeezelite. Airplay is just there for convenience (streaming from my PC and for my partner & guests), but I would like to get it to work in order to simplify my "modest" setup (which you can see here - though it is still, as always, under construction : https://pslweb.informatick.net/index).
 
Last edited:
Status
This old topic is closed. If you want to reopen this topic, contact a moderator using the "Report Post" button.