peppyalsa - ALSA plugin for VU Meters and Spectrum Analyzers

peppyalsa plugin is the result of the long and productive discussion in the PeppyMeter thread:
https://www.diyaudio.com/forums/pc-based/291010-peppymeter.html


peppyalsa is the ALSA plugin which sends a current audio volume level to a named pipe. Any application written in any language (e.g. C, C++, Java, Python etc.) can read that data from the other end of the named pipe and use it for its own purposes. The most common usage is displaying volume level either in GUI or in some hardware device.


Another functionality provided by peppyalsa is a Spectrum Analyzer. The plugin sends amplitude signal for each frequency band to a specified named pipe. Any application can read that data from the other end of the named pipe and either display it in GUI or in some hardware device.


peppyalsa.png



More details about plugin can be found on the wiki pages:
Home * project-owner/peppyalsa.doc Wiki * GitHub
 
I'm using the following .asoundrc for the peppyalsa plugin:


Code:
pcm.!default {
        type plug
        slave.pcm "softvol_and_peppyalsa"
}

ctl.!default {
        type hw
        card 0
}

pcm.peppyalsa {
        type meter
        slave.pcm "hw:0,0"
        scopes.0 peppyalsa
}

pcm.softvol_and_peppyalsa {
        type softvol
        slave.pcm "peppyalsa"
        control {
                name "PCM"
                card 0
        }
}

pcm_scope.peppyalsa {
        type peppyalsa
        decay_ms 400
        meter "/home/pi/myfifo"
        meter_max 100
        meter_show 0
        spectrum "/home/pi/myfifosa"
        spectrum_max 100
        spectrum_size 30
}

pcm_scope_type.peppyalsa {
        lib /usr/local/lib/libpeppyalsa.so
}

pcm.dsp0 peppyalsa
And I use the following .asoundrc when I use equalizer plugin:


Code:
pcm.!default {
  type plug
  slave.pcm plugequal;
}
ctl.!default {
  type hw card 0
}
ctl.equal {
  type equal;
}
pcm.plugequal {
  type equal;
  slave.pcm "plughw:0,0";
}
pcm.equal {
  type plug;
  slave.pcm plugequal;
}
Now I'd like to use both: equalizer and peppyalsa plugins. But when I merge these two files together there is no sound:


Code:
pcm.!default {
  type plug
  slave.pcm plugequal;
}
ctl.!default {
  type hw card 0
}
ctl.equal {
  type equal;
}
pcm.plugequal {
  type equal;
  slave.pcm softvol_and_peppyalsa;
}
pcm.equal {
  type plug;
  slave.pcm plugequal;
}
pcm.peppyalsa {
        type meter
        slave.pcm "hw:0,0"
        scopes.0 peppyalsa
}
pcm.softvol_and_peppyalsa {
        type softvol
        slave.pcm "peppyalsa"
        control {
                name "PCM"
                card 0
        }
}
pcm_scope.peppyalsa {
        type peppyalsa
        decay_ms 400
        meter "/home/pi/myfifo"
        meter_max 100
        meter_show 0
        spectrum "/home/pi/myfifosa"
        spectrum_max 100
        spectrum_size 30
}
pcm_scope_type.peppyalsa {
        lib /usr/local/lib/libpeppyalsa.so
}
pcm.dsp0 peppyalsa
Just wondering what I'm doing wrong here ? :confused:
 
My 2 cents the difference between equal and merged - the flexible plughw:0.0 slave in working equal vs. stubborn slave.pcm "hw:0,0" slave in the merged config.

I highly recommend testing complicated alsa configs with aplay -v (verbose) which outputs details of all the plugins involved in the chain. IMO the plug plugin in equal version does something important to satisfy the soundcard/driver requirements you are not aware of.
 
hmm, tried to change hw to plughw. The result was the same:
Code:
pi@raspberrypi:~ $ aplay -v /usr/share/sounds/alsa/Side_Left.wav
Playing WAVE '/usr/share/sounds/alsa/Side_Left.wav' : Signed 16 bit Little Endian, Rate 48000 Hz, Mono
ALSA lib pcm_params.c:2162:(snd1_pcm_hw_refine_slave) Slave PCM not usable
aplay: set_params:1270: Broken configuration for this PCM: no configurations available
 
I simplified the file:
Code:
pcm.!default {
  type plug
  slave.pcm myequal;
}

pcm.myequal {
    type equal;
    slave.pcm mypeppy;
}

pcm.mypeppy {
    type meter
    slave.pcm "plughw:0,0"
    scopes.0 peppyalsa
}

pcm_scope.peppyalsa {
    type peppyalsa
    decay_ms 400
    meter "/home/pi/myfifo"
    meter_max 100
    meter_show 0
    spectrum "/home/pi/myfifosa"
    spectrum_max 100
    spectrum_size 30
}

pcm_scope_type.peppyalsa {
    lib /usr/local/lib/libpeppyalsa.so
}
If I use it like that I have the error message:
Code:
pi@raspberrypi:~ $ aplay /usr/share/sounds/alsa/Side_Left.wav
Playing WAVE '/usr/share/sounds/alsa/Side_Left.wav' : Signed 16 bit Little Endian, Rate 48000 Hz, Mono
aplay: pcm_meter.c:1216: snd_pcm_scope_s16_get_channel_buffer: Assertion `s16->buf_areas' failed.
Aborted by signal Aborted...
If I replace 'myequal' block by this one:
Code:
pcm.myequal {
    type equal;
    slave.pcm "plughw:0,0";
}
it works fine but there is no peppyalsa functionality.
If I use just peppyalsa:
Code:
pcm.!default {
  type plug
  slave.pcm mypeppy;
}
it works fine but then there is no equalizer. So each of them separately works fine but there is some issue when they work together.


It looks like 'equal' plugin does something with PCM signal.
 
Code:
pi@raspberrypi:~ $ aplay /usr/share/sounds/alsa/Side_Left.wav -v
Playing WAVE '/usr/share/sounds/alsa/Side_Left.wav' : Signed 16 bit Little Endian, Rate 48000 Hz, Mono
Plug PCM: Route conversion PCM (sformat=S16_LE)
  Transformation table:
    0 <- 0
    1 <- 0
Its setup is:
  stream       : PLAYBACK
  access       : RW_INTERLEAVED
  format       : S16_LE
  subformat    : STD
  channels     : 1
  rate         : 48000
  exact rate   : 48000 (48000/1)
  msbits       : 16
  buffer_size  : 24000
  period_size  : 6000
  period_time  : 125000
  tstamp_mode  : NONE
  tstamp_type  : GETTIMEOFDAY
  period_step  : 1
  avail_min    : 6000
  period_event : 0
  start_threshold  : 24000
  stop_threshold   : 24000
  silence_threshold: 0
  silence_size : 0
  boundary     : 1572864000
Slave: Linear Integer <-> Linear Float conversion PCM (FLOAT_LE)
Its setup is:
  stream       : PLAYBACK
  access       : MMAP_INTERLEAVED
  format       : S16_LE
  subformat    : STD
  channels     : 2
  rate         : 48000
  exact rate   : 48000 (48000/1)
  msbits       : 16
  buffer_size  : 24000
  period_size  : 6000
  period_time  : 125000
  tstamp_mode  : NONE
  tstamp_type  : GETTIMEOFDAY
  period_step  : 1
  avail_min    : 6000
  period_event : 0
  start_threshold  : 24000
  stop_threshold   : 24000
  silence_threshold: 0
  silence_size : 0
  boundary     : 1572864000
Slave: alsaequal
Its setup is:
  stream       : PLAYBACK
  access       : MMAP_INTERLEAVED
  format       : FLOAT_LE
  subformat    : STD
  channels     : 2
  rate         : 48000
  exact rate   : 48000 (48000/1)
  msbits       : 32
  buffer_size  : 24000
  period_size  : 6000
  period_time  : 125000
  tstamp_mode  : NONE
  tstamp_type  : GETTIMEOFDAY
  period_step  : 1
  avail_min    : 6000
  period_event : 0
  start_threshold  : 24000
  stop_threshold   : 24000
  silence_threshold: 0
  silence_size : 0
  boundary     : 1572864000
Slave: Meter PCM
Its setup is:
  stream       : PLAYBACK
  access       : MMAP_INTERLEAVED
  format       : FLOAT_LE
  subformat    : STD
  channels     : 2
  rate         : 48000
  exact rate   : 48000 (48000/1)
  msbits       : 32
  buffer_size  : 24000
  period_size  : 6000
  period_time  : 125000
  tstamp_mode  : NONE
  tstamp_type  : GETTIMEOFDAY
  period_step  : 1
  avail_min    : 6000
  period_event : 0
  start_threshold  : 24000
  stop_threshold   : 24000
  silence_threshold: 0
  silence_size : 0
  boundary     : 1572864000
Slave: Plug PCM: Linear Integer <-> Linear Float conversion PCM (S16_LE)
Its setup is:
  stream       : PLAYBACK
  access       : MMAP_INTERLEAVED
  format       : FLOAT_LE
  subformat    : STD
  channels     : 2
  rate         : 48000
  exact rate   : 48000 (48000/1)
  msbits       : 32
  buffer_size  : 24000
  period_size  : 6000
  period_time  : 125000
  tstamp_mode  : NONE
  tstamp_type  : GETTIMEOFDAY
  period_step  : 1
  avail_min    : 6000
  period_event : 0
  start_threshold  : 24000
  stop_threshold   : 24000
  silence_threshold: 0
  silence_size : 0
  boundary     : 1572864000
Slave: Hardware PCM card 0 'bcm2835 ALSA' device 0 subdevice 0
Its setup is:
  stream       : PLAYBACK
  access       : MMAP_INTERLEAVED
  format       : S16_LE
  subformat    : STD
  channels     : 2
  rate         : 48000
  exact rate   : 48000 (48000/1)
  msbits       : 16
  buffer_size  : 24000
  period_size  : 6000
  period_time  : 125000
  tstamp_mode  : NONE
  tstamp_type  : GETTIMEOFDAY
  period_step  : 1
  avail_min    : 6000
  period_event : 0
  start_threshold  : 24000
  stop_threshold   : 24000
  silence_threshold: 0
  silence_size : 0
  boundary     : 1572864000
  appl_ptr     : 0
  hw_ptr       : 0
aplay: pcm_meter.c:1216: snd_pcm_scope_s16_get_channel_buffer: Assertion `s16->buf_areas' failed.
Aborted by signal Aborted...
 
Please follow the aplay -v output.

The alsaequal plugin requires FLOAT_LE, as written in its README GitHub - raedwulf/alsaequal . That is why the plug plugin before converts to FLOAT_LE.

The Meter PCM plugin does not exclude FLOAT_LE from its input formats, that is why alsa-lib feeds float_le happily from equal to meter.

No change is specified, alsa-lib assumes the meter plugin will keep the format (float_le) at its output. The actual card hw:0 bcm2835 does not accept float_le (logically), therefore the plug plugin in between kicks in to convert from float_le to S16_LE. Everything is nice and happy.

However, upon start the meter plugin will feed the incoming float samples to its code which works only for int - thus the failure.

Alsaequal does notify alsa-lib about its input format limitation - alsaequal/pcm_equal.c at master * raedwulf/alsaequal * GitHub

Meter does no such notification - alsa-lib/pcm_meter.c at master * tiwai/alsa-lib * GitHub . In other words it says "I accept anything" which is not true. IMO it fails at alsa-lib/pcm_meter.c at master * tiwai/alsa-lib * GitHub when it receives samples with FLOAT_LE format.

Put a slave definition requesting conversion to S16_LE between alsaequal and meter plugins. But such operation will limit resolution of your chain to 16bits. You may try S32_LE and see in aplay -v whether the meter plugin outputs the same format or cuts length to 16bits only. If so, you would need to split the chain in two branches and downsample to S16 in the branch with meter plugin only.
 
Thank you for very detailed analysis. That's raising the questions - does it mean that hardware allows maximum 16 bit signal?

Probably the best solution would be to add one more case to the pcm_meter.c in function s16_enable:
case SND_PCM_FORMAT_FLOAT_LE:
I can raise the issue for alsa-lib but that will take months if they will pay attention to this at all. Another way is to make my own version of the alsa-lib.

If all these plugins (equal and meter) transform the signal then they probably should not be used for feeding the hardware. So maybe it makes sense to split the signal into three streams each of them will feed
- equal plugin
- meter plugin
- hardware
Do you know any example of similar configuration? Actually the signal should pass through the equal plugin otherwise it defeats the purpose of the plugin :)
Thanks in advance!
 
Last edited:
does it mean that hardware allows maximum 16 bit signal?

It is a problem of the meter plugin. I do not know your hardware capabilities.

The correct solution would be adding the input format specs to meter plugin so that alsa-lib does not feed it with float. If you send a patch to alsa-devel mailing list, it would be included right away, if correct.

The easiest solution for you is to tell alsa-lib to feed the meter plugin with s16_le.

Something like ALSA project - the C library reference: PCM (digital audio) plugins

Code:
pcm.myequal {
    type equal;
    slave.pcm "flexiblepeppy";
}

pcm.flexiblepeppy {
        type plug
        slave {
                pcm "mypeppy"
                format S16_LE # or some higher
        }
}

Yes, splitting the code should be better. I would try the example of Advanced Linux Sound Architecture / Re: [Alsa-user] Proper syntax of "copy" plugin - plugin multi.
 
Thank you, I'll try different plugins (plug, lfloat, copy, multi) in the evening (PST) and let you know the results. The syntax of the 'multi' plugin scares me :)

As far as I know Raspberry Pi 3 on-board audio can output about 11 bit at 14KHz through 3.5mm jack. In this case any signal conversions are not so critical but for any HAT DACs it's important to minimize that.
 
Here are some results.
First, the output from the plain meter plugin:
Code:
pcm.peppy {
  type meter
  slave.pcm "hw:0,0"
  scopes.0 peppyalsa
}
Output:
Code:
pi@raspberrypi:~ $ aplay -D peppy /usr/share/sounds/alsa/Side_Left.wav -v > out.txt
Playing WAVE '/usr/share/sounds/alsa/Side_Left.wav' : Signed 16 bit Little Endian, Rate 48000 Hz, Mono
Meter PCM
Its setup is:
  stream       : PLAYBACK
  access       : RW_INTERLEAVED
  format       : S16_LE
  subformat    : STD
  channels     : 1
  rate         : 48000
  exact rate   : 48000 (48000/1)
  msbits       : 16
  buffer_size  : 24000
  period_size  : 6000
  period_time  : 125000
  tstamp_mode  : NONE
  tstamp_type  : MONOTONIC
  period_step  : 1
  avail_min    : 6000
  period_event : 0
  start_threshold  : 24000
  stop_threshold   : 24000
  silence_threshold: 0
  silence_size : 0
  boundary     : 1572864000
Slave: Hardware PCM card 0 'bcm2835 ALSA' device 0 subdevice 0
Its setup is:
  stream       : PLAYBACK
  access       : MMAP_INTERLEAVED
  format       : S16_LE
  subformat    : STD
  channels     : 1
  rate         : 48000
  exact rate   : 48000 (48000/1)
  msbits       : 16
  buffer_size  : 24000
  period_size  : 6000
  period_time  : 125000
  tstamp_mode  : NONE
  tstamp_type  : MONOTONIC
  period_step  : 1
  avail_min    : 6000
  period_event : 0
  start_threshold  : 24000
  stop_threshold   : 24000
  silence_threshold: 0
  silence_size : 0
  boundary     : 1572864000
  appl_ptr     : 0
  hw_ptr       : 0
Pay attention that the audio signal is mono - channels: 1

After numerous iterations some of which even caused segmentation fault I found the following working configurations:


Configuration #1 without 'multi' plugin:
Code:
pcm.!default {
  type plug
  slave.pcm myequal;
}

pcm.myequal {
    type equal;
    slave.pcm reformat;
}

pcm.reformat {
  type lfloat
  slave {
    pcm "mypeppy"
    format S16_LE
  }
}

pcm.mypeppy {
    type meter
    slave.pcm "plughw:0,0"
    scopes.0 peppyalsa
}

pcm_scope.peppyalsa {
    type peppyalsa
    decay_ms 400
    meter "/home/pi/myfifo"
    meter_max 100
    meter_show 0
}

pcm_scope_type.peppyalsa {
    lib /usr/local/lib/libpeppyalsa.so
}
Output:
Code:
pi@raspberrypi:~ $ aplay /usr/share/sounds/alsa/Side_Left.wav -v > out.txt
Playing WAVE '/usr/share/sounds/alsa/Side_Left.wav' : Signed 16 bit Little Endian, Rate 48000 Hz, Mono
Plug PCM: Route conversion PCM (sformat=S16_LE)
  Transformation table:
    0 <- 0
    1 <- 0
Its setup is:
  stream       : PLAYBACK
  access       : RW_INTERLEAVED
  format       : S16_LE
  subformat    : STD
  channels     : 1
  rate         : 48000
  exact rate   : 48000 (48000/1)
  msbits       : 16
  buffer_size  : 24000
  period_size  : 6000
  period_time  : 125000
  tstamp_mode  : NONE
  tstamp_type  : GETTIMEOFDAY
  period_step  : 1
  avail_min    : 6000
  period_event : 0
  start_threshold  : 24000
  stop_threshold   : 24000
  silence_threshold: 0
  silence_size : 0
  boundary     : 1572864000
Slave: Linear Integer <-> Linear Float conversion PCM (FLOAT_LE)
Its setup is:
  stream       : PLAYBACK
  access       : MMAP_INTERLEAVED
  format       : S16_LE
  subformat    : STD
  channels     : 2
  rate         : 48000
  exact rate   : 48000 (48000/1)
  msbits       : 16
  buffer_size  : 24000
  period_size  : 6000
  period_time  : 125000
  tstamp_mode  : NONE
  tstamp_type  : GETTIMEOFDAY
  period_step  : 1
  avail_min    : 6000
  period_event : 0
  start_threshold  : 24000
  stop_threshold   : 24000
  silence_threshold: 0
  silence_size : 0
  boundary     : 1572864000
Slave: alsaequal
Its setup is:
  stream       : PLAYBACK
  access       : MMAP_INTERLEAVED
  format       : FLOAT_LE
  subformat    : STD
  channels     : 2
  rate         : 48000
  exact rate   : 48000 (48000/1)
  msbits       : 32
  buffer_size  : 24000
  period_size  : 6000
  period_time  : 125000
  tstamp_mode  : NONE
  tstamp_type  : GETTIMEOFDAY
  period_step  : 1
  avail_min    : 6000
  period_event : 0
  start_threshold  : 24000
  stop_threshold   : 24000
  silence_threshold: 0
  silence_size : 0
  boundary     : 1572864000
Slave: Linear Integer <-> Linear Float conversion PCM (S16_LE)
Its setup is:
  stream       : PLAYBACK
  access       : MMAP_INTERLEAVED
  format       : FLOAT_LE
  subformat    : STD
  channels     : 2
  rate         : 48000
  exact rate   : 48000 (48000/1)
  msbits       : 32
  buffer_size  : 24000
  period_size  : 6000
  period_time  : 125000
  tstamp_mode  : NONE
  tstamp_type  : GETTIMEOFDAY
  period_step  : 1
  avail_min    : 6000
  period_event : 0
  start_threshold  : 24000
  stop_threshold   : 24000
  silence_threshold: 0
  silence_size : 0
  boundary     : 1572864000
Slave: Meter PCM
Its setup is:
  stream       : PLAYBACK
  access       : MMAP_INTERLEAVED
  format       : S16_LE
  subformat    : STD
  channels     : 2
  rate         : 48000
  exact rate   : 48000 (48000/1)
  msbits       : 16
  buffer_size  : 24000
  period_size  : 6000
  period_time  : 125000
  tstamp_mode  : NONE
  tstamp_type  : GETTIMEOFDAY
  period_step  : 1
  avail_min    : 6000
  period_event : 0
  start_threshold  : 24000
  stop_threshold   : 24000
  silence_threshold: 0
  silence_size : 0
  boundary     : 1572864000
Slave: Plug PCM: Hardware PCM card 0 'bcm2835 ALSA' device 0 subdevice 0
Its setup is:
  stream       : PLAYBACK
  access       : MMAP_INTERLEAVED
  format       : S16_LE
  subformat    : STD
  channels     : 2
  rate         : 48000
  exact rate   : 48000 (48000/1)
  msbits       : 16
  buffer_size  : 24000
  period_size  : 6000
  period_time  : 125000
  tstamp_mode  : NONE
  tstamp_type  : GETTIMEOFDAY
  period_step  : 1
  avail_min    : 6000
  period_event : 0
  start_threshold  : 24000
  stop_threshold   : 24000
  silence_threshold: 0
  silence_size : 0
  boundary     : 1572864000
  appl_ptr     : 0
  hw_ptr       : 0
Configuration #2 with 'multi' plugin:



Code:
pcm.!default {
  type plug
  slave.pcm {
    type multi
    slaves {
      a { pcm "myequal" channels 2 }
      b { pcm "reformat" channels 2 }
    }
    bindings [
      { slave a channel 0 }
      { slave a channel 1 }
      { slave b channel 0 }
      { slave b channel 1 }
    ]
  }
  ttable [
    [ 1 0 1 0 ]
    [ 0 1 0 1 ]
  ]
}

pcm.myequal {
  type equal;
  slave.pcm "plughw:0,0"
}

pcm.reformat {
  type lfloat
  slave {
    pcm "mypeppy"
    format S16_LE
  }
}

pcm.mypeppy {
  type meter
  slave.pcm {type null}
  scopes.0 peppyalsa
}

pcm_scope.peppyalsa {
  type peppyalsa
  decay_ms 400
  meter "/home/pi/myfifo"
  meter_max 100
  meter_show 0
}

pcm_scope_type.peppyalsa {
    lib /usr/local/lib/libpeppyalsa.so
}
Output:
Code:
pi@raspberrypi:~ $ aplay /usr/share/sounds/alsa/Side_Left.wav -v > out.txt
Playing WAVE '/usr/share/sounds/alsa/Side_Left.wav' : Signed 16 bit Little Endian, Rate 48000 Hz, Mono
Plug PCM: Route conversion PCM (sformat=S16_LE)
  Transformation table:
    0 <- 0
    1 <- none
    2 <- 0
    3 <- none
Its setup is:
  stream       : PLAYBACK
  access       : RW_INTERLEAVED
  format       : S16_LE
  subformat    : STD
  channels     : 1
  rate         : 48000
  exact rate   : 48000 (48000/1)
  msbits       : 16
  buffer_size  : 24000
  period_size  : 6000
  period_time  : 125000
  tstamp_mode  : NONE
  tstamp_type  : GETTIMEOFDAY
  period_step  : 1
  avail_min    : 6000
  period_event : 0
  start_threshold  : 24000
  stop_threshold   : 24000
  silence_threshold: 0
  silence_size : 0
  boundary     : 1572864000
Slave: Linear Integer <-> Linear Float conversion PCM (FLOAT_LE)
Its setup is:
  stream       : PLAYBACK
  access       : MMAP_INTERLEAVED
  format       : S16_LE
  subformat    : STD
  channels     : 4
  rate         : 48000
  exact rate   : 48000 (48000/1)
  msbits       : 16
  buffer_size  : 24000
  period_size  : 6000
  period_time  : 125000
  tstamp_mode  : NONE
  tstamp_type  : GETTIMEOFDAY
  period_step  : 1
  avail_min    : 6000
  period_event : 0
  start_threshold  : 24000
  stop_threshold   : 24000
  silence_threshold: 0
  silence_size : 0
  boundary     : 1572864000
Slave: Multi PCM
  Channel bindings:
    0: slave 0, channel 0
    1: slave 0, channel 1
    2: slave 1, channel 0
    3: slave 1, channel 1
Its setup is:
  stream       : PLAYBACK
  access       : MMAP_NONINTERLEAVED
  format       : FLOAT_LE
  subformat    : STD
  channels     : 4
  rate         : 48000
  exact rate   : 48000 (48000/1)
  msbits       : 32
  buffer_size  : 24000
  period_size  : 6000
  period_time  : 125000
  tstamp_mode  : NONE
  tstamp_type  : GETTIMEOFDAY
  period_step  : 1
  avail_min    : 6000
  period_event : 0
  start_threshold  : 24000
  stop_threshold   : 24000
  silence_threshold: 0
  silence_size : 0
  boundary     : 1572864000
Slave #0: alsaequal
Its setup is:
  stream       : PLAYBACK
  access       : MMAP_INTERLEAVED
  format       : FLOAT_LE
  subformat    : STD
  channels     : 2
  rate         : 48000
  exact rate   : 48000 (48000/1)
  msbits       : 32
  buffer_size  : 24000
  period_size  : 6000
  period_time  : 125000
  tstamp_mode  : NONE
  tstamp_type  : GETTIMEOFDAY
  period_step  : 1
  avail_min    : 6000
  period_event : 0
  start_threshold  : 24000
  stop_threshold   : 24000
  silence_threshold: 0
  silence_size : 0
  boundary     : 1572864000
Slave: Plug PCM: Linear Integer <-> Linear Float conversion PCM (S16_LE)
Its setup is:
  stream       : PLAYBACK
  access       : MMAP_INTERLEAVED
  format       : FLOAT_LE
  subformat    : STD
  channels     : 2
  rate         : 48000
  exact rate   : 48000 (48000/1)
  msbits       : 32
  buffer_size  : 24000
  period_size  : 6000
  period_time  : 125000
  tstamp_mode  : NONE
  tstamp_type  : GETTIMEOFDAY
  period_step  : 1
  avail_min    : 6000
  period_event : 0
  start_threshold  : 24000
  stop_threshold   : 24000
  silence_threshold: 0
  silence_size : 0
  boundary     : 1572864000
Slave: Hardware PCM card 0 'bcm2835 ALSA' device 0 subdevice 0
Its setup is:
  stream       : PLAYBACK
  access       : MMAP_INTERLEAVED
  format       : S16_LE
  subformat    : STD
  channels     : 2
  rate         : 48000
  exact rate   : 48000 (48000/1)
  msbits       : 16
  buffer_size  : 24000
  period_size  : 6000
  period_time  : 125000
  tstamp_mode  : NONE
  tstamp_type  : GETTIMEOFDAY
  period_step  : 1
  avail_min    : 6000
  period_event : 0
  start_threshold  : 24000
  stop_threshold   : 24000
  silence_threshold: 0
  silence_size : 0
  boundary     : 1572864000
  appl_ptr     : 0
  hw_ptr       : 0
Slave #1: Linear Integer <-> Linear Float conversion PCM (S16_LE)
Its setup is:
  stream       : PLAYBACK
  access       : MMAP_INTERLEAVED
  format       : FLOAT_LE
  subformat    : STD
  channels     : 2
  rate         : 48000
  exact rate   : 48000 (48000/1)
  msbits       : 32
  buffer_size  : 24000
  period_size  : 6000
  period_time  : 125000
  tstamp_mode  : NONE
  tstamp_type  : GETTIMEOFDAY
  period_step  : 1
  avail_min    : 6000
  period_event : 0
  start_threshold  : 24000
  stop_threshold   : 24000
  silence_threshold: 0
  silence_size : 0
  boundary     : 1572864000
Slave: Meter PCM
Its setup is:
  stream       : PLAYBACK
  access       : MMAP_INTERLEAVED
  format       : S16_LE
  subformat    : STD
  channels     : 2
  rate         : 48000
  exact rate   : 48000 (48000/1)
  msbits       : 16
  buffer_size  : 24000
  period_size  : 6000
  period_time  : 125000
  tstamp_mode  : NONE
  tstamp_type  : GETTIMEOFDAY
  period_step  : 1
  avail_min    : 6000
  period_event : 0
  start_threshold  : 24000
  stop_threshold   : 24000
  silence_threshold: 0
  silence_size : 0
  boundary     : 1572864000
Slave: Null PCM
Its setup is:
  stream       : PLAYBACK
  access       : MMAP_INTERLEAVED
  format       : S16_LE
  subformat    : STD
  channels     : 2
  rate         : 48000
  exact rate   : 48000 (48000/1)
  msbits       : 16
  buffer_size  : 24000
  period_size  : 6000
  period_time  : 125000
  tstamp_mode  : NONE
  tstamp_type  : GETTIMEOFDAY
  period_step  : 1
  avail_min    : 6000
  period_event : 0
  start_threshold  : 24000
  stop_threshold   : 24000
  silence_threshold: 0
  silence_size : 0
  boundary     : 1572864000
This is better though still not correct as the signal is stereo but should be mono. At least these configurations don't cause any errors and segmentation faults.
 
Look at the equal source code alsaequal/pcm_equal.c at master * raedwulf/alsaequal * GitHub Just like the plugin notifies alsa-lib about its supported format, it also does tell the chain about the number of channels it requires. If you track the field "channels", you will eventually get to line alsaequal/pcm_equal.c at master * raedwulf/alsaequal * GitHub . If not specified in .asoundrc, it uses the default of 2 alsaequal/pcm_equal.c at master * raedwulf/alsaequal * GitHub

IMO that is the reason the first plug in the chain converts from mono to stereo using the mono track for both channels.