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.
I have redone my home work. For a 2 ways Xover to a "multi"virtual device, based on Richard Taylor template, should it be like below:
Code:
 [FONT=Calibri]ecasound  \
         -a:pre -i:mysong.mp3 -pf:pre.ecp -o:loop,1 \
         -a:woofer,tweeter -i:loop,1 \
         -a:woofer -pf:woofer.ecp -chorder:1,2,0,0 \
         -a:tweeter -pf:tweeter.ecp -chorder:0,0,1,2 \
         -a:woofer,tweeter -f:16,4,44100 -el:mTAP,0,0.006,0,0.006 -o:alsa,multi[/FONT]

JMF
 
I have redone my home work. For a 2 ways Xover to a "multi"virtual device, based on Richard Taylor template, should it be like below:
Code:
 [FONT=Calibri]ecasound  \
         -a:pre -i:mysong.mp3 -pf:pre.ecp -o:loop,1 \
         -a:woofer,tweeter -i:loop,1 \
         -a:woofer -pf:woofer.ecp -chorder:1,2,0,0 \
         -a:tweeter -pf:tweeter.ecp -chorder:0,0,1,2 \
         -a:woofer,tweeter -f:16,4,44100 -el:mTAP,0,0.006,0,0.006 -o:alsa,multi[/FONT]

JMF

That's it exactly. When using mTAP you should "gather" all your channels together into one stream of N channels and then pass it through one call of mTAP. mTAP is therefore used as the last LADSPA plugin in the overall chain, and once mTAP has been applied the signal can be sent to the output device(s).

When using multiple output devices (multiple DACs not slaved together like you have done) the user must first split the N-channel stream into parts in a similar way that one splits the input into woofer and tweeter 'channels' using an ecasound loop. Off the top of my head, I think it would look something like this:

Code:
ecasound  \
         -a:pre -i:mysong.mp3 -pf:pre.ecp -o:loop,1 \
         -a:woofer,tweeter -i:loop,1 \
         -a:woofer -pf:woofer.ecp -chorder:1,2,0,0 \
         -a:tweeter -pf:tweeter.ecp -chorder:0,0,1,2 \
         -a:all -el:mTAP,0,0.006,0,0.006 -o loop,2 \
         -a:DAC1,DAC2 -i:loop,2 \
         -a:DAC1 -chorder:1,2 -f:16,4,44100 -o:alsa,DAC1
         -a:DAC2 -chorder:3,4 -f:16,4,44100 -o:alsa,DAC2

One might be able to use a single formatting option (-f:x,y,z) on the input instead of on each output because the ecasound documentation states the following:
-f:sample_format,channel,sample-rate,interleaving
Sets the audio stream parameters for subsequent audio objects.
 
I did the final check of the new ACDf filters and used my soundcard to make sure the frequency and phase behavior of each filter was correct. Looks like this is ready to go, but I need to double check the documentation and package up the files before it's posted to the web page.

I will post here when it's ready for download, likely before the weekend.
 
Hello,

I'm really not so good with LADSPA and mTAP. I don't succeed to solve error messages I have in my ecasound command. I have tried different configurations, but always get the same message:

ecasound: ERROR: [ECA-SESSION] : "Invalid argument, unable to parse: "-el:mTAP,0,0.006,0,0.006""

When I type:
Code:
ecasound           -a:pre -i:HeCanOnlyHoldHer.flac -f:16,2,44100 -pf:pre.ecp -o:loop,1          -a:woofer,tweeter -i:loop,1          -a:woofer -pf:woofer.ecp -chorder:1,0,2,0          -a:tweeter -pf:tweeter.ecp -chorder:0,1,0,2          -a:all -el:mTAP,0,0.006,0,0.006 -o:loop,2          -a:DAC1,DAC2 -i:loop,2          -a:DAC1 -chorder:1,3 -f:16,2,44100 -o:alsa,front:FXAUDIOD802          -a:DAC2 -chorder:2,4 -f:16,2,44100 -o:alsa,front:FXAUDIOD802_1 -d
I get the error message (-d)
Code:
...
(audiofx) Setting samplerate to 44100 for object Inverter. Old value 384000.
(eca-object-factory) Creating chain operator "Channel select"
(eca-object-factory) Setting parameters:  = 0.000src-ch-2 = 1.000 =
... 0.000src-ch-4 = 2.000
(audiofx) Setting samplerate to 44100 for object Channel select. Old value
... 384000.
(eca-object-factory) Creating LADSPA-plugin "mTAP v1.0: Multi-channel
... fractional delay"
(eca-object-factory) Setting parameters: channel 1 delay in milliseconds =
... 0.000, channel 2 delay in milliseconds = 0.006, channel 3 delay in
... milliseconds = 0.000, channel 4 delay in milliseconds = 0.006, channel
... 5 delay in milliseconds = 0.000, channel 6 delay in milliseconds =
... 0.000, channel 7 delay in milliseconds = 0.000, channel 8 delay in
... milliseconds = 0.000
(eca-chainsetup-parser) ERROR: Exactly one chain should be selected when
... adding chain operators.
(eca-chainsetup-parser) WARNING: Only 14+0 of the expected 27 parameters
... were recognized successfully.
(eca-chainsetup) Chainsetup "untitled-chainsetup"
(eca-chainsetup) Deleting chain "pre".
(eca-chainsetup) Deleting chain "woofer".
(eca-chainsetup) Deleting chain "tweeter".
(eca-chainsetup) Deleting chain "DAC1".
(eca-chainsetup) Deleting chain "DAC2".
(eca-chainsetup) Deleting audio db-client "HeCanOnlyHoldHer.flac".
(audioio-db-client) destructor HeCanOnlyHoldHer.flac.
(eca-chainsetup) Deleting audio object "HeCanOnlyHoldHer.flac".
(eca-chainsetup) Deleting loop device "loop".
---
ecasound: ERROR: [ECA-SESSION] : "Invalid argument, unable to parse: "-el:mTAP,0,0.006,0,0.006""
The key message seems to be:
Code:
(eca-chainsetup-parser) ERROR: Exactly one chain should be selected when
... adding chain operators.

If I suppress the mTAP filter, then the command is parsed. I also succeeded to use the command without fault in a simple line like
Code:
ecasound -b 100 -i HeCanOnlyHoldHer.flac -el:mTAP,0,0.006 -f:16,2,44100 -o:alsa,front:FXAUDIOD802


JMF
 
Last edited:
@JMF: A hint of the problem is here:
Code:
(eca-object-factory) Setting parameters: channel 1 delay in milliseconds =
... 0.000, channel 2 delay in milliseconds = 0.006, channel 3 delay in
... milliseconds = 0.000, channel 4 delay in milliseconds = 0.006, channel
... 5 delay in milliseconds = 0.000, channel 6 delay in milliseconds =
... 0.000, channel 7 delay in milliseconds = 0.000, channel 8 delay in
... milliseconds = 0.000
This indicates that the chain being passed to the mTAP plugin has 8 channels (or more, possibly). This probably means that -a:all does not combine the four channels from woofer with the four channels with tweeter. In fact "all" supposedly gathers ALL the streams together, meaning it also might be gathering the input stream and the pre stream along with woofer and tweeter! Sorry, that was my mistake suggesting "all".

Please try this:
Code:
ecasound -d -z:mixmode,sum
         -a:pre -i:HeCanOnlyHoldHer.flac -f:16,2,44100 -pf:pre.ecp -o:loop,1
         -a:woofer,tweeter -i:loop,1
         -a:woofer -pf:woofer.ecp -chorder:1,0,2,0
         -a:tweeter -pf:tweeter.ecp -chorder:0,1,0,2
         -a:woofer,tweeter -el:mTAP,0,0.006,0,0.006 -o:loop,2
         -a:DAC1,DAC2 -i:loop,2
         -a:DAC1 -chorder:1,3 -f:16,2,44100 -o:alsa,front:FXAUDIOD802
         -a:DAC2 -chorder:2,4 -f:16,2,44100 -o:alsa,front:FXAUDIOD802_1
The above uses "-z:mixmode,sum". When you use "a:woofer,tweeter" this should mix the four channels of woofer with the four channels of tweeter. Since the channels in woofer with sound correspond to the channels in tweeter with nothing (the zero channel assignment) you get a four-channel stream with woofer1, tweeter1, woofer2, tweeter2.

The ecasound output should show only four channels for mTAP (not the eight listed previously in the debug output).

Please let me know if that works for you.
 
Actually, the ecasound debug into might still show 8 channels for mTAP... I wrote the code assuming up to 8 input channels and any that are not explicitly supplied by a chain are "filled in" by ecasound with dummy input (and output I think).

Give the suggested code a try. If that doesn't work I will have to try and reproduce it here on my system to figure out what is wrong and how to do it another way.
 
Hi Charlie,

I tried the propose command, and I have the same error message. I'm not so surprised as I had already tried something similar with my multi virtual devaice, and it had failed also.

Even with the new command, in the debug messages, I see 8 channels filled.

I'm puzzled by the error message
ERROR: Exactly one chain should be selected when ... adding chain operators.
 
Progress: something like this seems to work where I feed mTAP without previous mix in the -a. Have to go working now, but I'll study the thing this evening

Code:
ecasound -d -z:mixmode,sum \
         -a:pre -i:HeCanOnlyHoldHer.flac -f:16,2,44100 -pf:pre.ecp -o:loop,1 \
         -a:woofer,tweeter -i:loop,1 \
         -a:woofer -pf:woofer.ecp -chorder:1,0,2,0 \
         -a:tweeter -pf:tweeter.ecp -chorder:0,1,0,2 \
         -a:woofer,tweeter  -o:loop,2 \
         -a:output -i:loop,2 -el:mTAP,0,0.006,0,0.006 -f:16,4,44100 -o:alsa,multi
JMF
 
Hi Charlie,

I tried the propose command, and I have the same error message. I'm not so surprised as I had already tried something similar with my multi virtual devaice, and it had failed also.

Even with the new command, in the debug messages, I see 8 channels filled.

I'm puzzled by the error message
ERROR: Exactly one chain should be selected when ... adding chain operators.

The 8 channels is actually the expected behavior. All channels must be accommodated by one mTAP plugin. In order to do this, you need to write the code for the maximum number of channels that you might need. In this case I chose 8 channels. The max channels can be adjusted in the code by editing the line:
Code:
static const int MAX_CHANNELS = 8; //maximum number of audio i/o channels
But this is only needed if more than 8 channels are needed.

When more channels exist for a plugin than there are supplied channels of audio, ecasound just silently adds "null channels" to the input and output.

I did a little more ecasound research. I think it might work if you change the following lines from this:
Code:
         -a:woofer,tweeter -el:mTAP,0,0.006,0,0.006 -o:loop,2
         -a:DAC1,DAC2 -i:loop,2
         -a:DAC1 -chorder:1,3 -f:16,2,44100 -o:alsa,front:FXAUDIOD802
         -a:DAC2 -chorder:2,4 -f:16,2,44100 -o:alsa,front:FXAUDIOD802_1
to this:
Code:
         -a:woofer,tweeter -o:loop,2
         -a:delay -i:loop,2 -el:mTAP,0,0.006,0,0.006  -o:loop,3
         -a:DAC1,DAC2 -i:loop,3
         -a:DAC1 -chorder:1,3 -f:16,2,44100 -o:alsa,front:FXAUDIOD802
         -a:DAC2 -chorder:2,4 -f:16,2,44100 -o:alsa,front:FXAUDIOD802_1
Ecasound seems to mix the channels from multiple chains when you list multiple chain identifiers after "-a:" but this is not 100% clear in the documentation and examples that I can find. It might be that you cannot then (on the same line) do other stuff like calling a LADSPA filter. So I have used another loop and then apply the mTAP to that on another line.

Unfortunately the details on this are not well documented as far as I can tell. Kai, the ecasound architect/developer, maintains a dev-list, so I can contact him and get an answer on this if we can't figure it out on our own.


EDIT: I see you posted again. The mixing is taking place with this line:
Code:
-a:woofer,tweeter  -o:loop,2
Looks like we are on the right track. You can try my edits as well if you would like.
 
Last edited:
@JMF:

Can you confirm that it is working for you, using the ecasound commands you posted?

I am not able to get it working using the commands I posted. I have been checking into this for awhile. mTAP is working fine - I can put it on the input line and use a very long delay (like 100 msec) that makes an echo and then I can hear everything fine. But when I try to use it the other way I get no audio on channels 3 and 4, only on channels 1 and 2. I will have to contact the developer because this seems to be some error with ecasound, or perhaps I just don't understand the correct way to do this with ecasound.
 
Hi Charlie,

Thank you to have worked so hard on my issue. I blocked for 1 or 2 hours on the same issue, nor having a channel. I progressively stripped down the command to the skeleton, and then simplified by step, starting from the end. At the end, I just found now a command that works:
Code:
ecasound -d -z:mixmode,sum -b 200  \
        -a:pre -i:HeCanOnlyHoldHer.flac -o:loop,1 \
        -a:woofer,tweeter -i:loop,1         \
     -a:woofer -chorder:2,0,1,0 \
        -a:tweeter -chorder:0,2,0,1 \
        -a:woofer,tweeter -f:16,4,44100 -o:loop,2 \
        -a:delay -i:loop,2 -o:loop,3 \
        -a:DAC1,DAC2 -i:loop,3 \
        -a:DAC1 -chorder:1,2 -f:16,2,44100 -o:alsa,front:FXAUDIOD802 \
        -a:DAC2 -chorder:1,2 -f:16,2,44100 -o:alsa,front:FXAUDIOD802_1

I had to add a formatting to 4 channels in line:
Code:
-a:woofer,tweeter -f:16,4,44100 -o:loop,2 \

I had the impression that this formatting to 4 channels was "implicit" after the commands manipulating 4 channels like -chorder:2,0,1,0 but it seems that it was not.

Ouf !!!

Thanks again for all the support !

JMF
 
And it works also with the complete command:
Code:
ecasound -d -z:mixmode,sum -b 200  \
        -a:pre -i:HeCanOnlyHoldHer.flac -o:loop,1 \
        -a:woofer,tweeter -i:loop,1         \
     -a:woofer -chorder:2,0,1,0 \
        -a:tweeter -chorder:0,2,0,1 \
        -a:woofer,tweeter -f:16,4,44100 -o:loop,2 \
        -a:delay --i:loop,2 -o:loop,3 \
        -a:DAC1,DAC2 -i:loop,3 \
        -a:DAC1 -chorder:1,2 -f:16,2,44100 -o:alsa,front:FXAUDIOD802 \
        -a:DAC2 -chorder:1,2 -f:16,2,44100 -o:alsa,front:FXAUDIOD802_1

ecasound syntax is definitly not obvious for me :p

JMF
 
Well that's not very intuitive... Now it all makes sense! It worked in Richard Taylor's example, and with your ecasound commands from post #428 because in both cases the -f:x,y,z format indicator is used on the same line!

I noticed you didn't actually use mTAP and I spotted a slight typo in this line:
Code:
-a:delay --i:loop,2 -o:loop,3 \
There are two dashes after -a:delay when you state the input for that chain. But anyway GREAT work! I will give it a try here on my system.

I posted a message (a couple of hours ago) to the ecasound dev mailing list asking for clarification. It's a little slow to produce an "answer" but I will let you know if/when I receive any information.
 
I am confirming that using the -f: format specifier indeed does work when mTAP is used in the "delay" chain as follows:
Code:
ecasound -d -z:mixmode,sum -B:rt -b:512  \
        -a:pre -i:HeCanOnlyHoldHer.flac -o:loop,1 \
        -a:woofer,tweeter -i:loop,1         \
        -a:woofer -chorder:1,0,2,0 \
        -a:tweeter -chorder:0,1,0,2 \
        -a:woofer,tweeter -f:16,4,44100 -o:loop,2 \
        -a:delay -i:loop,2 -el:mTAP,0,0.006,0,0.006 -o:loop,3 \
        -a:DAC1,DAC2 -i:loop,3 \
        -a:DAC1 -chorder:1,2 -f:16,2,44100 -o:alsa,front:FXAUDIOD802 \
        -a:DAC2 -chorder:3,4 -f:16,2,44100 -o:alsa,front:FXAUDIOD802_1
I made a couple of minor changes on the first line. I noticed you used -b 200. I assume you intended to specify the buffer size, in units of samples. In ecasound, the number you provide to the -b option must be a power of 2, e.g. "256" instead of "200" and there must be a colon after "-b" and then no space before the number of samples.

I also re-organized the channel assignments in a couple of places...

I found that if I did not first choose a mode using "-B:buffering_mode" then whatever I specified after -b:buffer_size was pre-empted or overridden. Since we are doing real time audio processing I always use -B:rt and then I set the buffer to -b:512 or -b:1024 (I typically use 48kHz data). Lower powers of 2 like 256 can work for the -b option but with continued reduction in the buffer_size you get some sporadic glitches and underruns. With -b:1024 I believe the latency is supposed to be on the order of 20 milliseconds at a 44.1kHz sample rate.
 
Last edited:
Hi,

Yes, I have to refine the exact command, but it works with the mTAP in the right place. I try now to integrate the thing in MPD, to be able to listen to music. My setup is not OK yet because the MPD daemon does not find the LADSPA plugins... A good night, and get fresh tomorrow to continue, and get a clean MPD / LADSPA combo.

All this is not so easy for the "Windows/Office" guy that I'm. Hopefully I have some old old old background about Unix and VMS. But I relearn the hard way.

Once working on the laptop, I will duplicate to the Orange Pi (over armbian).

JMF
 
Hi,

Yes, I have to refine the exact command, but it works with the mTAP in the right place. I try now to integrate the thing in MPD, to be able to listen to music. My setup is not OK yet because the MPD daemon does not find the LADSPA plugins... A good night, and get fresh tomorrow to continue, and get a clean MPD / LADSPA combo.

All this is not so easy for the "Windows/Office" guy that I'm. Hopefully I have some old old old background about Unix and VMS. But I relearn the hard way.

Once working on the laptop, I will duplicate to the Orange Pi (over armbian).

JMF

I use MPD as the source for a streaming audio system. Both because ecasound needs to know the bit depth, number of channels, and sample rate for incoming audio, because my DACs are only capable of handling up to a 48kHz sample rate, and because I only have so much WiFi bandwidth available for streaming I resample all audio as part of the MPD output to 16/48 and send it to an ALSA loopback. MPD has a very good resampling algorithm if you use the highest level of resampling quality.

When you configure the operating system to have an ALSA loopback it appears in the output of aplay as an ALSA "device". This means that audio applications can send audio to it (e.g. MPD) and other audio applications can accept audio from the 'output' of the loopback as their input. I do this, except MPD is on my server and ecasound is running on several clients. In between I use Gstreamer (and before used VLC) to stream the audio, accepting audio from the ALSA loopback on the server, streaming it to the clients, receiving it with another instance of Gstreamer/VLC and then using another loopback on the client to pass it on to ecasound.

In you case it's a bit simpler - you only need the ALSA loopback on the same computer as MPD and your DACs. If you are interested, I'd be happy to post my MPD configuration file and info on how to set up the loopback.

I think the other way to do it (which I think you will try to use) is to embed the entire ecasound command string into an MPD output. I don't have any experience with that, but it supposedly works just fine. You could probably put the ecasound string into a shell script (if yo know windows, this is like a batch file). I always do that and I could provide some help on doing so although it's very simple. Create a text file. On the first line enter the following:
Code:
#!/bin/bash
Paste your ecasound command string into the file below it, just like you would run it from the command line. You can use the backslash character at the end of each line (as usual) to make it more readable. Save the file and call it crossover.sh or whatever, just use the ".sh" extension so that you will know that it is a shell script. At the command line, type:
Code:
sudo chmod +x crossover.sh
This changes the permissions on the file so that the operating system knows it is an executable file. Now when you type
Code:
./crossover.sh
the ecasound command string will be executed and any output will show up on the screen. If you call this from within an MPD output the ecasound output will probably not be shown, I'm not sure. This would be alot cleaner than putting the whole ecasound string into MPD directly, and you can easily make changes by editing the crossover.sh file just like a text file (since it is a text file).
 
Last edited:
...looking forward to it, Charlie! Any changes to the control parameter format?

F.

No changes to the number of (seven), or order of appearance (filter_type, polarity, dB_gain, Fp, Qp, Fz, Qz), of the control parameters for ACDf...

But I did renumber the second order filters to follow the first order filters. So for example for first order there is:
TYPE DESCRIPTION
0 gain block
1 1st order LP
2 1st order HP
3 1st order AP
4 1st low shelf
5 1st high shelf

And for ACDf ver2.0 the available second order filters are numbered like this:
TYPE DESCRIPTION
21 2nd order LP
22 2nd order HP
23 2nd order AP
24 2nd order low shelf
25 2nd order high shelf
26 parametric EQ, digital form
27 2nd order notch
28 biquadratic filter

In that way you can remember that "5" is a treble shelving filter, 5 being the first order version and 25 being the second order version.

Now that I think about it, maybe I should have started numbering the first order filters with 11. Oh well, too late now.

The usage notes describe all of that in detail.
 
Hi Charlie,

The downloading link does not seems to work at the moment. It gives a 404 Error.

y the way, did yo finally changed the input parameters for the Shelf filtrs (center frequency instead of side frequencies) or did you keep t same as before?

Bst regards,

JMF
 
Status
This old topic is closed. If you want to reopen this topic, contact a moderator using the "Report Post" button.