11

So Pulseaudio has a built-in equilizer loaded with

module-equalizer-sink

According to http://www.freedesktop.org/wiki/Software/PulseAudio/Documentation/User/Equalizer, you can control it with the qpaeq GUI.

Is there a way to congfigure PA equilizer on a Xless system (running in session mode) ?

2
  • 1
    Since there's this python script that creates a GUI interface, it should be easy just to strip it down and using DBus directly.
    – Braiam
    Commented Oct 27, 2014 at 17:07
  • Unfortunately this is way above my knowledge.
    – kursus
    Commented Oct 27, 2014 at 17:50

4 Answers 4

7

Here's a script, adapteded from qpaeq that comes with Pulseaudio:

#!/usr/bin/env python
# pulse-set-eq
import os,math,sys
import dbus

# Source adapted from utils/qpaeq of PulseAudio

def connect(): # copied from qpaeq
    try:
        if 'PULSE_DBUS_SERVER' in os.environ:
            address = os.environ['PULSE_DBUS_SERVER']
        else:
            bus = dbus.SessionBus() # Should be UserBus, but D-Bus doesn't implement that yet.
            server_lookup = bus.get_object('org.PulseAudio1', '/org/pulseaudio/server_lookup1')
            address = server_lookup.Get('org.PulseAudio.ServerLookup1', 'Address', dbus_interface='org.freedesktop.DBus.Properties')
        return dbus.connection.Connection(address)
    except Exception as e:
        sys.stderr.write('There was an error connecting to pulseaudio, '
                         'please make sure you have the pulseaudio dbus '
                         'module loaded, exiting...\n')
        sys.exit(-1)

def get_sink(str):
    connection=connect()
    path='/org/pulseaudio/core1/sink%s'%str
    sink=connection.get_object(object_path=path)
    return sink

args = sys.argv[1:]
if len(args)<5:
    print("Usage: "+sys.argv[0]+" SINK_NUM CHANNEL_NUM PREAMP_VALUE FREQ1 COEF1 [FREQ2 COEF2...]")
    sys.exit()


sinknum = args.pop(0);
sink = get_sink(sinknum);

prop_iface='org.freedesktop.DBus.Properties'
eq_iface='org.PulseAudio.Ext.Equalizing1.Equalizer'
sink_props=dbus.Interface(sink,dbus_interface=prop_iface)

def get_eq_attr(attr):
    return sink_props.Get(eq_iface,attr)

sample_rate=get_eq_attr('SampleRate')
filter_rate=get_eq_attr('FilterSampleRate')
nchannels=get_eq_attr('NChannels')

sys.stderr.write('channels %d, sample rate: %f, filter sample rate: %f\n'%
    (nchannels, sample_rate, filter_rate))

channel = int(args.pop(0));
preamp = float(args.pop(0));

freqs = [];
coeffs = [];
while len(args) > 0:
    if len(args)==1:
        sys.stderr.write('Odd number of frequency/amplification arguments (%d)\n'%(len(freqs)*2+1))
        sys.exit(-1)
    sys.stderr.write('(%s, %s)\n'%(args[0],args[1]))
    freqs.append(float(args.pop(0)))
    coeffs.append(float(args.pop(0)))

#sys.stderr.write("freqs: "+str(freqs)+'\n');

freqs = list([int(round(x*filter_rate/sample_rate)) for x in freqs])
#sys.stderr.write("translated freqs: "+str(freqs)+'\n');

freqs = [0]+freqs+[filter_rate//2];
coeffs = [coeffs[0]]+coeffs+[coeffs[-1]];
#sys.stderr.write("proper freqs: "+str(freqs)+'\n');

# for some reason this fixes the types of the arguments to SeedFilter
sink=dbus.Interface(sink,dbus_interface=eq_iface)

# set the filter coefficients
sink.SeedFilter(channel,freqs,coeffs,preamp)

Usage :

Get the sink number using pacmd list-sinks, then

./pulse-set-eq SINK_NUM CHANNEL_NUM PREAMP_VALUE FREQ1 COEF1 [FREQ2 COEF2 …]

Note that it seems the CHANNEL_NUM 0 will correspond to the first channel, 1 to the second, etc., and if you use the actual number of channels (e.g. 2 if you have two channels) it will set the equalization for all channels.

You can check the applied settings anytime using qpaeq.

Prerequisites :

Note that first you want to load the equalizer module as well as the DBus protocol module:

pactl load-module module-dbus-protocol
pactl load-module module-equalizer-sink sink_name=... sink_master=...
pactl set-default-sink ...

Playing with the script

Then make some noise, or music or whatever:

play -n synth pinknoise gain -10

Then call the script with the sink number, the channel index you want the equalizer to apply to, a preamp (scaling) factor, and a list of (frequency, coefficient) pairs. The frequency list doesn't have to be dense, since it is interpolated (see seed_filter in pulseaudio/src/modules/module-equalizer-sink.c) to get the filter coefficients. If you specify the total number of channels as the channel index then the update applies to all channels. Use pacmd list-sinks to get the sink number.

For example, if the sink number is $SINKNUM and it has 2 channels, then this resets the equalizer to all 1's, as you can verify by opening qpaeq:

./pulse-set-eq $SINKNUM 2 1.0    100 1.0

Here 100 Hz is arbitrary; the list needs to be not empty and can't start with zero. The frequencies must be between 0 and 32768 (the maximum for me, not sure if it is configurable, see the filter_rate variable above - this is half that). The script uses the amplification coefficients of the smallest and largest frequencies specified on the command line, for the frequencies below and above these, respectively, so in this case the whole spectrum will be assigned an amplification rate of 1.0. At this setting, the equalizer will leave the signal unchanged (in theory at least).

Be careful not to damage your speakers, but for example you can play around by creating pink noise and setting the equalizer to a spike (at 100x amplification) at a single frequency (500Hz):

./pulse-set-eq $SINKNUM 2 1.0    499 0 500 100 501 0

When I do this, I can hear a discrete succession of tones of different random volumes, all at 500Hz, which I presume are belonging to successive DFT windows in the implementation of the filter. It is somewhat pleasant. Playing music through this filter is amusing. Such a sharp "bandpass" would not be possible using a normal graphical equalizer with no command-line version.

The following example makes a filter that goes up and down in frequency, a bit like a siren. Obviously you have to have some music playing or noise or something to hear the effect.

SINKNUM=12; NCHAN=2;
while true; do
    for i in $(seq 500 10 1500) $(seq 1500 -10 500); do
        ./pulse-set-eq $SINKNUM $NCHAN 1 \
            0 1 $(( $i - 300 )) 1 \
            $i 5 $(( $i + 300 )) 1 \
            32768 1;
    done;
done
1
  • Since the sink seems to change at each new connection, it is helpful to have an alias or a bash script with pactl load-module module-equalizer-sink && /opt/qpaeq_se $(pacmd list-sinks|grep "*"|awk '{print $NF}') 2 ${EQ_SETTINGS}, witth ${EQ_SETTINGS} the settings you wish. Commented Mar 23, 2021 at 15:42
3

The pulseaudio equalizer is reading his settings in the user file ~/.config/pulse/equalizerrc

To display it:

cat ~/.config/pulse/equalizerrc

So, as example, to give a value of 10DB on the 5th band of the eq, and directly ear the change:

sed -i '19s/.*/10.0/' ~/.config/pulse/equalizerrc | pulseaudio-equalizer toggle

To explain furthermore, sed will replace all line numbered 19, and will replace it by 10.0 on the config file, then the equalizer is restarted/toggled to get the result.

1
  • 5
    So this file doesn't seem to exist in my version of pulseaudio (9.0), on my machine you instead have a tdb file equalizer-state.tdb, this can be viewed with tdbtool however the data seems to be in the wonderfully structured form of a 262180 byte array representing a data structure, which looks like it contains both strings and an array of numbers.
    – Att Righ
    Commented Jan 28, 2017 at 19:45
2

The answer is that you can't with simple native commands.

You can with samething more complicate, like:

$ pactl load-module module-ladspa-sink sink_name=FonsParamEQ master=alsa_output.pci-0000_03_06.0.analog-stereo plugin=filters label=Parametric1 control=1,0,1,49,0.5,3,1,1000,0.5,2,1,10000,0.5,3,1,13500,0.5,-12

Wich I dont know how it works, I mentioned as a reference for you to search ;-)

But the python script works.

More info... With "qpaeq" you will find "~/.config/pulse/equalizer-presets.tdb" which is "Samba Trivial DB", which can be seen with tdb-tool (as commented).

The file refered as "~/.config/pulse/equalizerrc" belongs to other package wich is "pulseaudio-equalizer" (other app, that for me its much better)

I dont hace karma to comment the other post, sorry for redudancy.

I hope it helps.

Regards

1
-2

I believe the command is pacmd.

EDIT:

If you go to:

/usr/share/pulseaudio/alsa-mixer/profile-sets

You will find a number of configuration files. You may want to try editing default.conf.

3
  • 1
    related: pactl.
    – HalosGhost
    Commented Oct 27, 2014 at 17:11
  • 3
    Could you be more specific ? These are the commands to control the whole Pulseaudio system. It doesn't seem to have equalizer related options.
    – kursus
    Commented Oct 27, 2014 at 17:49
  • "Default profile definitions for the ALSA backend of PulseAudio. This is used as fallback for all cards that have no special mapping assigned". This has nothing to do with the question.
    – kursus
    Commented Oct 30, 2014 at 1:47

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .