Pulseaudio and module-echo-cancel YOCTO recipe

I have the same problem as shown in this post and I am trying to integrate the webrtc echo canceller from pulseaudio package into my system.
I have included the following lines in local.conf

IMAGE_INSTALL:append = “ pulseaudio pulseaudio-server pulseaudio-misc”
DISTRO_FEATURES:append = “ pulseaudio”

I have included the following lines in ./layers/openembedded-core/meta/recipes-multimedia/pulseaudio/pulseaudio.inc

EXTRA_OEMESON += “-Dwebrtc-aec=enabled”
EXTRA_OECONF += “--enable-webrtc-aec”
DEPENDS += “webrtc-audio-processing”
RDEPENDS:pulseaudio-server = " \
    pulseaudio-module-echo-cancel \
    ...... \

The result is that we have pulseaudio on board but not the echo canceller. The list of available modules is as follows.

pactl list modules short
0       module-device-restore
1       module-stream-restore
2       module-card-restore
3       module-augment-properties
4       module-switch-on-port-available
5       module-udev-detect      tsched=0
6       module-native-protocol-unix
7       module-default-device-restore
9       module-always-sink
10      module-null-sink        sink_name=auto_null sink_properties='device.description="Dummy Output"'
11      module-intended-roles
12      module-suspend-on-idle
13      module-position-event-sounds
14      module-role-cork
15      module-filter-heuristics
16      module-filter-apply

If I try to load the echo cancellation module I get an error but the module-echo-cancel.so library is located in the path /usr/lib/pulse-15.0/modules/module-echo-cancel.so.

pactl load-module module-echo-cancel
Failure: Module initialization failed

could you help me with the recipe?

Best regards,
Julian

Hi, I’m the Toradex AI Assistant. I’m in early beta, and I would appreciate your feedback.
The Toradex Support team will follow up with you shortly!

Did you like my answer?

:+1: :-1:


Hello Julian,

Integrating the WebRTC echo canceller from the PulseAudio package into your system and encountering issues with the echo cancellation module not being recognized or initialized correctly can be challenging. Based on the information you’ve provided, it seems you have taken the correct steps to include PulseAudio and its echo cancellation module in your Yocto build. However, the module initialization failure suggests there might be a missing dependency or a configuration issue.

Here are a few steps and checks to ensure the echo cancellation module is correctly integrated and functional:

  1. Verify Dependencies: Ensure that all dependencies required by the echo cancellation module are correctly included in your build. The webrtc-audio-processing package is crucial, but double-check if there are any other dependencies specific to your version of PulseAudio.

  2. PulseAudio Version Compatibility: Verify that the version of PulseAudio you are using supports the WebRTC echo canceller with the configuration options you are using. Sometimes, newer or older versions might have different requirements or support different features.

  3. Configuration Options: The options -Dwebrtc-aec=enabled and --enable-webrtc-aec you’ve used seem correct, but it’s worth checking the PulseAudio documentation or the ./configure --help output to ensure these options are valid for enabling the WebRTC echo canceller in your PulseAudio version.

  4. Module Path: The error message you encountered when trying to load the echo cancellation module suggests a possible issue with the module’s path or with the module itself. Verify that the path /usr/lib/pulse-15.0/modules/module-echo-cancel.so is correct and that the module file has the correct permissions.

  5. PulseAudio Configuration: Check the PulseAudio configuration files to ensure they are set up to load the echo cancellation module correctly. Sometimes, manual edits to configuration files are necessary to enable specific modules.

  6. Debugging PulseAudio: You can try running PulseAudio in verbose mode to get more detailed error messages that might help identify the problem. Use the command pulseaudio -vvvv to start PulseAudio in verbose mode, then attempt to load the module again.

  7. Check for SELinux/AppArmor: If your system uses SELinux or AppArmor, ensure that these security modules are not preventing PulseAudio or its modules from functioning correctly. You might need to adjust policies to allow the echo cancellation module to load and operate.

If after these checks the issue persists, it might be helpful to consult the Pulse

Please, also check if these links can help you solve your problem:

How to Setup Bluetooth Audio Profiles (Linux) | Toradex Developer Center.

Hello @jbruno,

We are looking into the issue you linked.
I will coordinate with the team working on this and try to reproduce the echo canceller issue to hopefully find a solution.

When there are further updates I will send them here.

Best Regards,
Bruno

Hello @jbruno,

I apologize for the delay on this topic.

We were initially unable to use the HFP profile with pulseaudio.
Therefore we did not reproduce the exact problem that you have.

That being said, one of our domain experts is looking into the echo problem and is working to reproduce the problem, so updates are expected soon.

I see that there was another post from one of your colleagues with some additional information here: Integrating Pulseaudio with YOCTO Recipe - #2 by ToradexAI
Is it OK if we continue following this topic there?

Best Regards,
Bruno

Hi @bruno.tx,
I don’t understand why they can’t reproduce the bug. Using your BSP and making the modifications I mention in the recipes you should get the same failure. So far we have not tried to use HFP profile with pulseaudio either.

As @ferranmc says, we have detected another bug. After creating a new user, the developers of pulseaudio advise against using the root user, we are not able to listen to the playback of an audio file.

adduser test
usermod -aG audio test
pulseaudio --kill
pulseaudio --start
paplay test_audio.wav

When listing the sound cards from pulseaudio, we see that the result is null. We understand that this may be the reason for not being able to listen to the audio.

pactl list cards

Does the same thing happen to you? Could you help us with this bug?

Best regards,
Julián

Hello @jbruno,

I tested this again and was able to run into the issue you reported.

By setting log-level = debug in /etc/pulse/daemon.conf and running pulseaudio in the foreground, you can see the error that happens when trying to load module-echo-cancel:

root@verdin-imx8mm-06898561:~# pulseaudio -vvv &
...
root@verdin-imx8mm-06898561:~# pactl load-module module-echo-cancel
I: [pulseaudio] client.c: Created 3 "Native client (UNIX socket client)"
D: [pulseaudio] protocol-native.c: Protocol version: remote 35, local 35
I: [pulseaudio] protocol-native.c: Got credentials: uid=0 gid=0 success=1
D: [pulseaudio] protocol-native.c: SHM possible: yes
D: [pulseaudio] protocol-native.c: Negotiated SHM: yes
D: [pulseaudio] protocol-native.c: Memfd possible: yes
D: [pulseaudio] protocol-native.c: Negotiated SHM type: shared memfd
D: [pulseaudio] memblock.c: Using shared memfd memory pool with 1024 slots of size 64.0 KiB each, total size is 64.0 MiB, maximum usable slot size is 65472
D: [pulseaudio] srbchannel.c: SHM block is 65472 bytes, ringbuffer capacity is 2 * 32712 bytes
D: [pulseaudio] protocol-native.c: Enabling srbchannel...
D: [pulseaudio] module-augment-properties.c: Looking for .desktop file for pactl
D: [pulseaudio] protocol-native.c: Client enabled srbchannel.
E: [pulseaudio] module-echo-cancel.c: Can't cancel echo between a sink and its monitor
E: [pulseaudio] module.c: Failed to load module "module-echo-cancel" (argument: ""): initialization failed.
Failure: Module initialization failed
I: [pulseaudio] client.c: Freed 3 "pactl"
I: [pulseaudio] protocol-native.c: Connection died.

Please give special attention to the following line from the log:

E: [pulseaudio] module-echo-cancel.c: Can't cancel echo between a sink and its monitor

Therefore, I don’t believe this is a problem with the compilation of pulseaudio or the echo cancellation module, but you need to specify the source_master and the sink_master that module-echo-cancel needs to use, as documented it: Modules – PulseAudio


Regarding the problem with the card not being listed by pulseaudio, please make sure to select the correct device tree for the Dahlia Carrier Board before the first boot, preferably in your Yocto build.
The reason for this is that the default device tree which is loaded is the one for the Verdin Development Board, which uses a different audio codec than the one on the Dahlia Carrier Board.
From BSP 6.7.0, we made some changes that ensure that changing the device tree even after the first boot results in working audio when using alsa, however pulseaudio seems to not detect the audio codec if the device tree was wrong in the first boot.

Here is an example output with the audio codec properly detected in the Dahlia Carrier Board:

root@verdin-imx8mm-06898561:~# pactl list cards
Card #0
	Name: alsa_card.platform-sound-card
	Driver: module-alsa-card.c
	Owner Module: 6
	Properties:
		alsa.card = "0"
		alsa.card_name = "verdin-wm8904"
		alsa.long_card_name = "verdin-wm8904"
		device.bus_path = "platform-sound-card"
		sysfs.path = "/devices/platform/sound-card/sound/card0"
		device.form_factor = "internal"
		device.string = "0"
		device.description = "Built-in Audio"
		module-udev-detect.discovered = "1"
		device.icon_name = "audio-card"
	Profiles:
		HiFi: Default (sinks: 0, sources: 0, priority: 8000, available: yes)
		off: Off (sinks: 0, sources: 0, priority: 0, available: yes)
	Active Profile: HiFi

Best Regards,
Bruno

Hi @bruno.tx,
Using pulseaudio debug I found that I need to include some more packages in my image. I did that and I managed to load the default echo canceller.
When trying to load the webrtc canceller, pulseaudio does not recognise webrtc as a valid value for the aec_method argument. Try to run it and you will see the error in the pulseaudio debug.

load-module module-echo-cancel aec_method=webrtc

Checking the source code of module-echo-cancel.c I found that this value is valid for aec_method argument but that there is a conditional compilation that affects it, see HAVE_WEBRTC.
I have checked how this module is compiled and in the meson.build file nothing is indicated.
Something similar happens for the speex canceler.

My conclusion is that it would be necessary to tell the compiler HAVE_WEBRTC=1 in order to use this algorithm in the echo cancellation module. Do you know how we could do it?

On the other hand, in our image we already have the verdin-wm8904 card by default. The problem is that if we don’t stop the bluealsa service, the pactl command doesn’t list the audio card.

Best regards,
Julián

Hello @jbruno,

As pulseaudio uses the Meson build system, you should be able do add such configuration to the EXTRA_OEMESON variable which is used by the pulseaudio recipe.

Noted, therefore, if bluealsa ends up not being used, it could be removed from the image to avoid this conflict.

Best Regards,
Bruno

Hi @bruno.tx,

My knowledge of YOCTO is not very advanced and therefore it is not very clear to me how to tell the compiler of the echo cancellation module to activate the HAVE_WEBRTC variable. I have introduced this line in the local.conf

EXTRA_OEMESON:append:pn-pulseaudio-module-echo-cancel = " HAVE_WEBRTC=1"

when I run the module load

pactl load-module module-echo-cancel aec_method=webrtc

I still get the same error

E: [pulseaudio] module-echo-cancel.c: Invalid echo canceller implementation ‘webrtc’
E: [pulseaudio] module.c: Failed to load module “module-echo-cancel” (argument: “aec_method=webrtc”): initialization failed.
D: [pulseaudio] protocol-dbus.c: Interface org.PulseAudio.Core1.Client removed from object /org/pulseaudio/core1/client4
I: [pulseaudio] client.c: Freed 4 “pactl”
I: [pulseaudio] protocol-native.c: Connection died.

Can you tell me how to modify local.conf to enable this option?

On the other hand, I haven’t removed bluealsa from the image but I have disabled the service. For our application we need to connect via bluetooth the mobile with the imx8 and apply the echo canceller to the call.

Best regards,
Julian

Hello @jbruno,

I would actually recommend that you modify the pulseaudio recipe, by creating a .bbappend file in a custom Yocto layer.
With the .bbapend in an independent layer, the overall maintenance is reduced when compared to manually editing .bb or .inc files in existing layers.
The documentation on how to get this setup is available here: Custom meta layers, recipes and images in Yocto Project (hello-world examples) | Toradex Developer Center

That being said, if you are just testing this initially, you could even add this in the layers/openembedded-core/meta/recipes-multimedia/pulseaudio/pulseaudio.inc and you did previously:

EXTRA_OEMESON += “ -DHAVE_WEBRTC=1 ”

Best Regards,
Bruno

Hi @bruno.tx ,
I have added that line in the pulseaudio.inc file and it gives an error when generating the image.
Best regards,
Julián

Hello @jbruno,

What error do you get?
Maybe a required dependency is missing.

Best Regards,
Bruno

Hello @jbruno,

Looking further into the echo issue we found a simpler procedure to add module-echo-cancel to the Reference Multimedia Image.
You just need to add the following to the local.conf file:

IMAGE_INSTALL:append = " pulseaudio pulseaudio-misc webrtc-audio-processing"
DISTRO_FEATURES:append = " pulseaudio"
PACKAGECONFIG:append:pn-pulseaudio = " webrtc"

Changes to any of the pulseaudio recipe files can be reverted, as they are not needed.

Using an image with these changes, you should be able to use the following command:

load-module module-echo-cancel aec_method=webrtc

It should still give an error as is, as more arguments would need to be added to fit your use case. But the error is no longer related to the use of webrtc as the aec_method.

E: [pulseaudio] module-echo-cancel.c: Can't cancel echo between a sink and its monitor
E: [pulseaudio] module.c: Failed to load module "module-echo-cancel" (argument: "aec_method=webrtc"): initialization failed.

Best Regards,
Bruno

Dear @bruno.tx,
By including these changes in the local.conf file, the module is not included in the image.

IMAGE_INSTALL:append = " pulseaudio pulseaudio-misc webrtc-audio-processing"
DISTRO_FEATURES:append = " pulseaudio"
PACKAGECONFIG:append:pn-pulseaudio = " webrtc"

After executing the command:

pactl load-module module-echo-cancel aec_method=webrtc

The following error message appears:

E: [pulseaudio] ltdl-bind-now.c: Failed to open module module-echo-cancel.so: module-echo-cancel.so: cannot open shared object file: No such file or directory
E: [pulseaudio] module.c: Failed to open module “module-echo-echo-cancel”.
I: [pulseaudio] client.c: Freed 3 “pactl”.

Maybe there are some more modifications missing in the local.conf or pulseaudio.inc files?

Best regards,
Julián

Hello @jbruno,

I apologize the for the delay on this topic, it has been hard to get the calling feature to work on my setup.
However, one of our domain experts got a setup to work, which includes the use of the webrtc echo cancellation configuration.

The following script was used to configure pulseaudio and the bluetooth functionality:

#!/bin/bash

# to check if PulseAudio is running
check_pulseaudio() {
    ps aux | grep -i pulseaudio | grep -v grep > /dev/null
    return $?
}

echo "Killing and unblocking bluetooth"
rfkill unblock bluetooth

sleep 1
echo "Powering bluetooth" 
bluetoothctl power on

echo "Turn on agent"
bluetoothctl agent on 

sleep 1
echo "setting default agent"
bluetoothctl default-agent 

# Check for PulseAudio processes
process_id=$(ps aux | grep -i pulseaudio | grep -v grep | awk '{print $2}')

# If a PulseAudio process is found
if [ ! -z "$process_id" ]; then
    echo "PulseAudio process found with PID: $process_id"
    
    # Kill the PulseAudio process
    kill -9 $process_id
    
    # Verify if the process is killed
    if [ $? -eq 0 ]; then
        echo "PulseAudio process killed successfully."
    else
        echo "Failed to kill the PulseAudio process."
    fi
else
    echo "No PulseAudio process found."
fi

echo "starting Pulseaudio"
pulseaudio --start

# Wait for PulseAudio process to start
while ! check_pulseaudio; do
    echo "Waiting for PulseAudio to start..."
    sleep 1
done

echo "PulseAudio is now running."


echo "Loading sink/output device"
pactl load-module module-alsa-sink device=hw:0,0

sleep 1

#echo "Setting default sink/output"
#pactl set-default-sink alsa_output.hw_0_0

echo "Loading source/input"
pactl load-module module-alsa-source device=hw:0,0

#echo "Setting default source/input"
#pactl set-default-source alsa_input.hw_0_0

echo "Loading echo cancellation module"
pactl load-module module-echo-cancel sink_name=echosink source_name=echosource \
    aec_method=webrtc aec_args="analog_gain_control=0\ digital_gain_control=1" \
    source_master=alsa_input.hw_0_0 sink_master=alsa_output.hw_0_0

echo "Setting echo cancellation as default sink and source"
pactl set-default-sink echosink
pactl set-default-source echosource



echo "Enabling SCO "
hcitool -i hci0 cmd 0x3F 0x001D 0x00

echo "Device ready to connect/pair"

Please note that this was done with the bluealsa service disabled.

Best Regards,
Bruno

Hi @jbruno !

Were you able to test the script shared by @bruno.tx above?

Do you have any updates regarding this topic?

Best regards,

Dear @henrique.tx ,
I have tried but to my knowledge this script cannot be executed correctly. Pulseaudio needs to be run from a non-ROOT user and some commands in this script can only be run from the ROOT user. Here is the first dilemma.
I also miss some additional information:

  • Which profile they have activated from the card (pactl set-card-profile bluez_card.XX_XX_XX_XX_XX_XX_XX_XX_XX_XX_XX ???).
  • Have you modified the files /etc/asound.conf and /etc/dbus-1/system.d/bluetooth.conf ?

I look forward to more information.
Thank you very much for your help.
Best regards,
Julián

Hello @jbruno,

This script is intended to be ran as the root user.
From our testing you can run this script and pulseaudio will be initialized correctly.

We did no change to these configurations.
The profile change is done automatically and this is controlled by the connected device/phone.

That being said we have found some issues with this setup when using the Verdin iMX8MM, so please hold while we investigate this further.

Once we have more information we will send it on this thread.

Best Regards,
Bruno

Hello @jbruno,

Upon further investigation we have narrowed down the problem to the SDIO driver for the WiFi/Bluetooth module on the Verdin iMX8MM.
The setup from my message on the other thread works for the Verdin iMX8MP (which does not use the SDIO driver) and for the Verdin iMX8MM using an external bluetooth adapter.

We will continue to investigate this problem to understand where the bug is on the SDIO driver.

Best Regards,
Bruno

Hello @jbruno,

We have found some differences in the bluetooth packet behavior when using the SDIO driver for the WiFi/Bluetooth module on the Verdin iMX8MM.
This may be related to another bluetooth issue in this driver that we are looking into.

Unfortunately, there is still no workaround when using the integrated bluetooth module, but we continue to investigate this problem and I will send updates here when available.

Best Regards,
Bruno