Enabling Instant Noise Cancellation on Linux

Written by ojumah | Published 2022/06/26
Tech Story Tags: linux | linode | internet | open-source | fedora | arch-linux | linux-writing-contest | noise-cancellation

TLDRThis article focuses on configuring the Noise canceling plugin with PipeWire and creating a Virtual Source to use as an input for any application, even web-based applications like Google Meet and Microsoft teams.via the TL;DR App

In this article, I will be explaining how to cancel microphone noise on Linux.

Prerequisites:

  • PipeWire
  • Arch Linux or Fedora

The PipeWire is a multimedia framework built from scratch for very low latency processing of audio/video. One of the best features of Pipewire is that it provides a real-time capable plugin structure. The PipeWire daemon was built using this framework and is compatible with PulseAudio, JACK, ALSA, and GStreamer-based applications.

Is PipeWire a requirement?

No. You can configure this with PulseAudio. However, I have not tested it and verified it.

By default, Fedora comes with PipeWire, and most other distributions include the PulseAudio.

This article focuses on configuring the Noise canceling plugin with PipeWire and creating a Virtual Source to use as an input for any application, even web-based applications like Google Meet and Microsoft teams.

The RNNoise — a noise suppression library based on a recurrent neural network is the foundation of the Noice canceling plugin.

The Danylo Piliaiev develops and maintains the plugin, eliminating a wide range of noise origins like an airplane, construction, office/crowd, and computer fans.

1. Plugin Installation

Arch Linux:

To install the plugin on Arch Linux, you must use the noise-suppression-for-voice AUR package.

Execute the following command to install the package using `yay` an AUR helper.

$ yay -S noise-suppression-for-voice

or you can install without an AUR helper with the following commands:

$ sudo pacman -S git
$ git clone https://aur.archlinux.org/noise-suppression-for-voice.git
$ cd noise-suppression-for-voice
$ makepkg -si

Fedora:

The plugin can be installed on Fedora using the COPR repository. To configure this repository, enter the following command:

$ sudo dnf copr enable ycollet/linuxmao

To install the latest package, enter the following command:

$ sudo dnf install ladspa-noise-suppression-for-voice

Complete the above tasks to install the plugin binary into the location “/usr/lib/ladspa/librnnoise_ladspa.so”.

2. Create Filter chain for PipeWire

A filter chain allows inserting an arbitrary graph of LADSPA (Linux Audio Developer’s Simple Plugin API) and built-in plugins in front of a sink or a source to create a new Virtual filtered sink/source.

2.1 Create a configuration directory to store filter chain configuration files.

$ mkdir -p ~/.config/pipewire/

2.2 Create a filter chain file  input-filter-chain.conf.

You can use any name you prefer, but make sure to use it throughout the configuration.

$ vim ~/.config/pipewire/input-filter-chain.conf

You can use this to create a configuration file for a PipeWire filter chain as below.

Notice that the first filter graph node has a plugin property that points to the location.

plugin = /usr/lib/ladspa/librnnoise_ladspa.so

Paste the following content to the above file.

# Noise canceling source
#
# start with pipewire -c filter-chain/input-filter-chain.conf
#

context.properties = {
  log.level        = 0
}

context.spa-libs = {
  audio.convert.* = audioconvert/libspa-audioconvert
  support.*       = support/libspa-support
}

context.modules = [
      {   name = libpipewire-module-rtkit
          args = {
            #nice.level   = -11
            #rt.prio      = 88
            #rt.time.soft = 200000
            #rt.time.hard = 200000
          }
          flags = [ ifexists nofail ]
      }
      {   name = libpipewire-module-protocol-native }
      {   name = libpipewire-module-client-node }
      {   name = libpipewire-module-adapter }
      {   name = libpipewire-module-filter-chain
          args = {
              node.name =  "rnnoise_source"
              node.description =  "Noise Canceling source"
              media.name =  "Noise Canceling source"
              filter.graph = {
                  nodes = [
                      {
                          type = ladspa
                          name = rnnoise
                          plugin = /usr/lib/ladspa/librnnoise_ladspa.so
                          label = noise_suppressor_stereo
                          control = {
                              "VAD Threshold (%)" 50.0
                          }
                      }
                ]
          }
          capture.props = {
              node.passive = true
        }
        playback.props = {
              media.class = Audio/Source
        }
    }
}

3. Configuration

To load this filter chain to the PipeWire, we need to create a systemd service. The service we will be making as a systemd user instance and it will start at the first login.
The systemd user instance is a per-user process and not per-session.

3.1 Create the systemd user configuration directory if it does not exist.

$ mkdir -p ~/.config/systemd/user/

3.2 Create a new systemd unit file.

$ vim ~/.config/systemd/user/pipewire-input-filter-chain.service

Make sure to:

  • Replace the file name if you have used a different name for the filter chain configuration file.
  • Replace the <username> with your account username.

[Unit]

Description=PipeWire Input Filter Chain
After=pipewire.service
BindsTo=pipewire.service

[Service]
ExecStart=/usr/bin/pipewire -c /home/<username>/.config/pipewire/input-filter-chain.conf
Type=simple
Restart=on-failure

[Install] 
WantedBy=pipewire.service      

3.3 Reload systemd user unit files.

$ systemct --user daemon-reload

3.4 Enable the created systemd service.

$ systemct --user enable pipewire-input-filter-chain.service

Log out and log back in and check the sound control panel on your DE and you will see a new input source with the name “Noise canceling source”.

If you do not see the new Virtual Source device, please check the systemd service’s status and rectify any errors in the configuration if the service fails to start.

$ systemctl --user status pipewire-input-filter-chain.service

4. Finally, select the new audio source on applications.

Google Meet

Google meet provides a Noise cancellation option but I have deactivated it as the PipeWire plugin provided better voice quality compared to Google Meet's built-in method.

For other applications, the configuration would be similar.

Now you can make your meetings more effective and enjoy your podcasts and game streams without worrying about the background noise.

References:

Also published here.


Written by ojumah | Tech is my life.
Published by HackerNoon on 2022/06/26