LinuxQuestions.org
Help answer threads with 0 replies.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Software
User Name
Password
Linux - Software This forum is for Software issues.
Having a problem installing a new program? Want to know which application is best for the job? Post your question in this forum.

Notices


Reply
  Search this Thread
Old 06-28-2022, 02:01 PM   #1
poo.butt
LQ Newbie
 
Registered: Jun 2022
Posts: 7

Rep: Reputation: 1
Need help setting up an ALSA software ducker / sidechaining compressor


Hi guys, a bit of an advanced ALSA config question, hopefully someone can help me, I'll post what I have so far.

I'm trying to setup some software DSP, in particular, I want music to duck (lower its volume) when I speak into the microphone. This is for a streaming setup. To do this, there seem to be multiple ways, however, I'd like to do it with .asoundrc. Alternatives are using pulseaudio or jack or pipewire, but I'd rather do this using .asoundrc.

To achieve ducking, or sidechaining compression, I can use a LADSPA plugin, with the ladspa block in .asoundrc. I've already identified the plugin I want to use, at least for now, called sc3. It is part of swh plugins.

I'd also like to use two compressors, but getting one to work will be fine. The second one is for the Text To Speech feature, I want that to also be able to duck the music, but I want to be able to have my speech duck the TTS if need be, so it doesn't talk over me. So it's kind of a cascaded setup.

Below is a schematic of how I'd like this to work. I've used the bus metaphor to illustrate it. Basically I want to be able to control which streams go to the sidechain input of each of the two compressors.

https://i.imgur.com/UPhq4lj.png

Explanation: on the left you have a 5 line bus, the rightmost one are a stereo pair. MIC 1 and MIC 2 are just the left and right channels of the Mic In port on the motherboard. MUSIC is going to be the default pcm device, where most audio will be played from the PC: music, videos etc. TTS is going to be a secondary pcm device, where the TTS will be played. The big rectangles are sidechaining compressors, with input, output and sidechain (SC) input. PAN and VOL are just panning and volume, I think in alsa it's called softvol.

Here is what I've managed so far:

Code:
pcm.sc3plug {
        type ladspa
        slave.pcm "plughw:CARD=Generic,DEV=0";

        path "/usr/lib/ladspa";
        plugins [{
                label sc3
                policy none
                input {
                        # https://github.com/swh/ladspa/blob/master/sc3_1427.xml
                        controls [ 100 800 0 10 1 0 1 ]
                        bindings.0 left_in;
                        bindings.1 right_in;
                        bindings.2 sidechain;
                }
                output {
                        bindings.0 left_out
                        bindings.1 right_out
                }
        }]
}

pcm.sc3 {
        type plug
        slave.pcm "sc3plug";
        hint {
                show on
                description "SC3 Compressor"
        }
}
I'm currently getting the following error. I think I'm just not understanding bindings:
Code:
aplay -D sc3 poopy.wav
ALSA lib pcm_ladspa.c:1362:(snd_pcm_ladspa_parse_bindings) Unable to find an audio port (left_in) for channel 0
aplay: main:830: audio open error: Invalid argument
For starter, I'm not sure how to configure the inputs and the outputs of the ladspa block.

Please help, ALSA documentation seems so sparse.
 
Old 06-29-2022, 04:08 PM   #2
poo.butt
LQ Newbie
 
Registered: Jun 2022
Posts: 7

Original Poster
Rep: Reputation: 1
The diagram explains how I'd implement this with analog audio, but it seems I need to somehow restructure it so it works with the master/slave audio used in .asoundrc. However, I don't understand, for example, how I can get the 3 inputs that the compressor plugin needs. It has 3 inputs and 2 outputs: left in, right in, sidechain in, left out, right out. If I'm understanding correctly, the first master is the music pcm, and the last slaves are the hardware mic and hardware out. But somehow I can't figure out how to route from the music pcm, and join it with the sidechain, into a 3 channel stream, and then feed that into the compressor node.
 
Old 06-30-2022, 03:04 AM   #3
ondoho
LQ Addict
 
Registered: Dec 2013
Posts: 19,872
Blog Entries: 12

Rep: Reputation: 6053Reputation: 6053Reputation: 6053Reputation: 6053Reputation: 6053Reputation: 6053Reputation: 6053Reputation: 6053Reputation: 6053Reputation: 6053Reputation: 6053
This should be possible, but it won't be flexible, and your distro's alsa setup might interfere with things.
Good luck getting help with that - ALSA is a book with seven seals (and I only replied because you already took yourself out of zero reply status anyhow).

My recommendation: try for sure, but don't drive yourself mad trying. Switch to JACK which is designed for these kinds of things.
 
Old 06-30-2022, 04:39 AM   #4
poo.butt
LQ Newbie
 
Registered: Jun 2022
Posts: 7

Original Poster
Rep: Reputation: 1
Thanks, just trying to figure out how master/slave works in regard to input/output, with the ladspa plugin. I'll take another look at its source code. The only flexibility I need is to be able to mute and pan, and I've provisioned for that with the VOL blocks in my schematic, I'm assuming they're going to show up as volume controls in alsa mixer, and that I can control those from the command line.
 
Old 07-01-2022, 12:59 AM   #5
ondoho
LQ Addict
 
Registered: Dec 2013
Posts: 19,872
Blog Entries: 12

Rep: Reputation: 6053Reputation: 6053Reputation: 6053Reputation: 6053Reputation: 6053Reputation: 6053Reputation: 6053Reputation: 6053Reputation: 6053Reputation: 6053Reputation: 6053
I'd be interested to see how you solve this.
 
Old 07-01-2022, 03:37 AM   #6
poo.butt
LQ Newbie
 
Registered: Jun 2022
Posts: 7

Original Poster
Rep: Reputation: 1
I've emailed the guy who made the ladspa plugin for alsa, perhaps he knows how.
 
Old 07-01-2022, 12:06 PM   #7
poo.butt
LQ Newbie
 
Registered: Jun 2022
Posts: 7

Original Poster
Rep: Reputation: 1
so it looks like the slave can only be a playback or capture stream, not both at the same time:

https://i.imgur.com/5sSlc7C.png
 
1 members found this post helpful.
Old 07-02-2022, 09:23 AM   #8
poo.butt
LQ Newbie
 
Registered: Jun 2022
Posts: 7

Original Poster
Rep: Reputation: 1
I'm getting ready to reach a conclusion here. Because opening a pcm device is unidirectional, i.e. you can only open a pcm for capture or for playback, it is the nature of the client/slave chains to be unidirectional when instantiated. In effect, the asound config file is similar to a class in C++, and opening a pcm definition with aplay or arecord, or any ALSA client program, is similar to instantiating that class, either for capture or for playback. This, in turn, has the effect that you can't use a mic in a playback chain, which is what I need. I need the mic to be connected to the sidechain input of the LADSPA sc3 plugin, but I need the rest of the inputs and outputs of the plugin to be used in playback mode. So this might make it seem impossible to achieve what I want, but there is one more possibility, and that is, using dmix and dsnoop with the same ipc key, and opening TWO pcm definitions, one in playback and one in capture mode. This might work, but I haven't managed to get it to work. At this point I'm going against the grain, and I might just give up. I'll wait for the author of the ladspa plugin to respond and I'll report back here.

Next, I'm looking at 4 avenues: using jack, using pipewire, using pulseaudio, and possibly writing my own alsa plugin. The pulseaudio route seems to make most sense, because it's stable and I'm already using it, being forced so by Firefox and OBS. Writing my own plugin might or might not work, as it might be the case that alsa itself cannot effectively allow this setup. For jack, I don't like having to run jackd at startup, and for pipewire, it seems promising but it's too new to rely on, or at least it seems that way.
 
Old 07-11-2022, 12:35 AM   #9
poo.butt
LQ Newbie
 
Registered: Jun 2022
Posts: 7

Original Poster
Rep: Reputation: 1
I've used pipewire and a custom config file to setup most of what I wanted, they've been helpful on the IRC channel, just figuring out a few things, and dealing with occasional choppy audio, but this ended up being my choice.

I had to upgrade to debian testing so I could get wireplumber as the session manager.

I used a lv2 plugin instead of ladspa, I just couldn't get the ladspa one (sc3) to work.

Code:
context.modules = [{
        name = libpipewire-module-loopback
        args = {
                node.description "Default Loopback"
                audio.position = [ FL FR ]
                capture.props = {
                        media.class = Audio/Sink
                        node.name = my_sink
                        node.description = "Default Sink"
                        #node.latency = 1024/48000
                        #audio.rate = 44100
                        audio.channels = 2
                        audio.position = [ FL FR ]
                        #node.target = "my-default-sink"
                }
                playback.props = {
                        #media.class = Audio/Source
                        node.name = my_source
                        node.description = "Default Sink Out"
                        #node.latency = 1024/48000
                        #audio.rate = 44100
                        audio.channels = 2
                        audio.position = [ FL FR ]
                        #node.target = "effect_input.main_ducker"
                        #node.passive = true
                }
        }
}, {
        name = libpipewire-module-filter-chain
        args = {
                node.description = "TTS Ducker"
                media.name       = "TTS Ducker"
                filter.graph = {
                        nodes = [{
                                name = comp
                                type = lv2
                                plugin = "http://lsp-plug.in/plugins/lv2/sc_compressor_stereo"
                                control = {
                                        "enabled" = 1
                                        "sct" = 2
                                        "al" = 0.01
                                        "at" = 20
                                        "rt" = 250
                                        "cr" = 100
                                }
                        }]
                        inputs  = [ "comp:in_l" "comp:in_r" "comp:sc_l" "comp:sc_r" ]
                        outputs = [ "comp:out_l" "comp:out_r" ]
                }
                capture.props = {
                        node.name      = "effect_input.tts_ducker"
                        media.class    = Audio/Sink
                        audio.channels = 4
                        audio.position = [ FL FR SL SR ]
                }
                playback.props = {
                        node.name      = "effect_output.tts_ducker"
                        node.passive   = true
                        audio.channels = 2
                        audio.position = [ FL FR ]
                        node.target = "alsa-line-out"
                }
        }
}, {
        name = libpipewire-module-filter-chain
        args = {
                node.description = "Main Ducker"
                media.name       = "Main Ducker"
                filter.graph = {
                        nodes = [{
                                name = comp
                                type = lv2
                                plugin = "http://lsp-plug.in/plugins/lv2/sc_compressor_stereo"
                                control = {
                                        "enabled" = 1
                                        "sct" = 2
                                        "al" = 0.01
                                        "at" = 20
                                        "rt" = 250
                                        "cr" = 100
                                }
                        }]
                        inputs  = [ "comp:in_l" "comp:in_r" "comp:sc_l" "comp:sc_r" ]
                        outputs = [ "comp:out_l" "comp:out_r" ]
                }
                capture.props = {
                        node.name      = "effect_input.main_ducker"
                        media.class    = Audio/Sink
                        audio.channels = 4
                        audio.position = [ FL FR SL SR ]
                }
                playback.props = {
                        node.name      = "effect_output.main_ducker"
                        node.passive   = true
                        audio.channels = 2
                        audio.position = [ FL FR ]
                        node.target = "alsa-line-out"
                }
        }
}]
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Favorite data compressor computer_tom General 5 03-17-2006 09:47 PM
Audio player with dynamic range compressor pdevries Linux - Software 0 02-08-2006 07:26 AM
Commandline audio compressor, expander, equalizer fluoline Linux - Software 1 06-04-2005 08:56 PM
MPEG2 stream compressor recommendations? cheesekeeper Linux - Software 0 02-25-2005 05:30 PM

LinuxQuestions.org > Forums > Linux Forums > Linux - Software

All times are GMT -5. The time now is 02:23 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration