Peppymeter (peppyalsa) VU Meters with Roon?

I’ve managed to build a Pi+ 7" touchscreen running Roon Bridge, peppyalsa and peppymeter and the alsaloop trick.
It works, but it’s not ideal, as you need to group zones and it doesn’t like straying from 16/44.1 PCM, forget DSD…

So, I’ll be working on some ALSA-fu to get to the green box and get something totally transparent to Roon that will support whatever audio thrown at it. I’m pretty sure that ALSA has all the bits required and that it’s a matter of plumbing the correct configuration.
Basically, the green box is the magic trick.

Once all sorted, I’ll push a full documentation to @spockfish with the hope that it can make it into Ropieee


I also have a roon core on nuc i7, plus raspi from volumio and roon bridge. I would like to capture somehow the roon bridge signal for the display under the covers or vu indicators (without roon bridge after airplay, there is a reduction to 16/44, but the display works).
have any of you already done it and could help? thank you

Any chance that someone would be willing to help me get this up and running? I have a feeling I’m really close, but just making a dumb mistake.

Well then, give us details as to what you’ve achieved so far and where you think you’re stumbling…

Thank you. The two loopback options show up in roon, and there are 3 output options that show up in volumio (headphones, dummy, and loopback). The only combination that results in communication with volumio from roon is when the headphone device is selected in Roon and the output device in volumio is set to headphones. If any other combination is selected then volumio stops communicating with Roon.

Not being a Volumio user here, I think it’s probably better to check their fora.
While working on my Roon-dynamic-range-metering-bridge I think I’ve seen links to threads regarding setting up and using the peppy meter plugin…

Do you have peppy meter work as Volumio plug in yet?
If so, then just grouping with whatever zone you want it to display should do the trick, no?

Thanks but I’ll keep working this thread as this is the only thread I’ve found where people have had success doing this. Unless you’re using roon, there’s no reason to setup the loopback.

I finally had a chance to revisit this and want to say thanks to @ipeverywhere (and everyone else) for continuing to tinker around with this. With snd-aloop and alsaloop everything is working in my Pi streamer when I group the loopback device with the standard endpoint in Roon. Very cool.

I’ll post my full walkthrough later where I’ve distilled all of the above (plus a few other tweaks to PeppyMeter configs) to get everything working as a complete streamer + VU meters, but first I’m going to test building a basic Volumio streamer running RoonBridge and nothing but the VU meters which may be easier in the long run.

One problem I can’t figure out with the manual approach, though: My Pi streamers are all configured to run at 1024x768 but there are no Peppy Meter skins that fit that resolution, and I can’t figure out how to tell python3 to run at full screen. Anyone have any suggestions on running Peppy Meter at full screen with standard Pi resolutions?

1 Like

Two updates:

  • I gave Volumio a try and I have to say I’m liking their distro more and more as a Roon endpoint. There’s a newer tool called ‘volroon’ which is available as a plugin w/in Volumio that uses a web extension to display Now Playing and basic playback functions. No Now Playing support was a huge blocker for me and Volumio, glad to see it. BUT, no luck getting PeppyMeter to work with a Roon stream. I tried hacking around with asound.conf but couldn’t get it to work, which is a shame b/c it’s slick as a Volumio screensaver. I’m going to request Roon support b/c it’s a much more elegant solution than the manual implementation below.

  • I was able to fix the full screen issue and cobble together a super quick runbook for getting this up and running on a 3.5 TFT. It’s not 100% yet – autostart with peppymeter and alsaloop isn’t working, and there are still a few bumps that aren’t fully solid (see below), but it’s a great first PoC.

Quick walkthrough on getting this running on a standard Pi w/ screen:

  • Get the endpoint up and running with RoonBridge and your screen however you’d like. Once that’s working…
    • You’ll need to force your screen resolution to match one of the pre-scaled resolutions like 800x480 to use “large” meters
  • Install peppyalsa:
    • git clone GitHub - project-owner/peppyalsa
    • cd peppyalsa/
    • sudo apt-get install build-essential autoconf automake libtool libasound2-dev libfftw3-dev
    • aclocal && libtoolize
    • autoconf && automake --add-missing
    • ./configure && make
    • sudo make install
  • Make fifo
    • mkfifo ~/myfifo
  • Load snd-module
    • sudo modprobe snd-aloop (to load it now)
    • sudo echo ‘snd-aloop’ >> /etc/modules (to persist it after a reboot)
  • Run alsaloop
    • alsaloop -d -C “hw:Loopback,0,0” -P “peppyalsa” -l 1500 -b &
  • Grab PeppyMeter (you’ll need python3 if you don’t have it installed)
    • git clone GitHub - project-owner/PeppyMeter: PeppyMeter Repository
    • cd PeppyMeter
    • edit config.txt to choose “large” (assuming you set that resolution from above) and to choose your meters (or just leave it random for now to get started)
    • export DISPLAY=:0 && cd /home/pi/PeppyMeter/ && python3 /home/pi/PeppyMeter/ > /dev/null 2>&1 & (remove the background and redirects to /dev/null to test and see full output if you have issues)
  • In Roon, enable the Loopback PCM device now available for your Pi RoonBridge endpoint
  • Group the standard Alsa RoonBridge endpoint with the new Loopback PCM and you should be in business.

I’ve been running with this setup all day, rotating between a few different meters, and generally all is good, but I have had two issues with the above:

  • I had to set the latency (-l in alsaloop) really high to avoid buffer underrun issues. No idea why; everything in my env is connected over ethernet so it’s not a network issue. It does make the Peppy needles a bit less responsive.
  • After listening in this setup for a while, maybe ~30 minutes, the audio will become distorted, starting gradually and sounding mechanically until it becomes really robot-y and distorted. Ungrouping and regrouping in Roon fixes it. It may be something that I can correct in the loopback Roon settings, haven’t played around yet. Or maybe increasing the buffer?
1 Like

@rcrawley umfortunately I can’t be of any help on the resolution thing, but as a photographer I’m pretty handy in photoshop and might be able to adjust a couple of the backgrounds to fit the needed resolution for you.

If you need any help testing your instructions please feel free to DM me.

Thanks @312Elements! I think we were posting at the same time. :slight_smile: Forcing my Pi screen to a resolution that matched the “large” resolution for Peppy has worked for now, but thanks for the offer! My next step is to work out why launching Peppy via autostart isn’t working, but once that’s done and I have bootable VU Meters I may take you up on on that offer.

Also found this archive of different sized meters:

…and a few different options and resolutions embedded in this long thread:

1 Like

Fixed this issue (at least so far after a normal work day of streaming) by setting the resync delay on the alsaloop device in Roon to 500ms. Not really sure what this does but so far, so good.

I was also able to solve the load on boot issue by loading alsaloop in crontab:

$ crontab -e
@reboot /usr/bin/alsaloop -C hw:Loopback,0,0 -P peppyalsa -l 2000 -b > /tmp/alsaloop.log 2>&1 &

I had to jack the latency all the way up to 2000 to keep it stable, and am redirecting stdout and stderr to a temp log to debug future latency issues.

…an wrote a small script to load PeppyMeter:


export DISPLAY=:0 
cd /home/pi/PeppyMeter
python3 ./ > /tmp/peppymeter.log 2>&1 &

…that I call from ~/.config/lxsession/LXDE-pi/autostart:


And that did it. I now have a 3.5 TFT streamer running RoonBridge, out via USB to a Schiit stack with PeppyMeter working on boot. Now onto building a more permanent one with a wide screen LCD for the main streaming room. Thanks again for all the notes in this thread!


Nice job!

Would you mind checking CPU load just for me to compare with my dynamic-range-metering-bridge?
Thanks a lot for considering!

Load is high, floating around 35 for user processes while streaming. Biggest offenders are mutter and Xorg. Makes me wonder if you can run pygame without X (something like fbi for displaying pictures w/o X). A quick search looks like it should be possible…

@rcrawley I’m out of town for a long weekend but will give this a go upon returning. If you happen to get to eventually start from scratch on a new unit at some point would you be willing to do a starting from scratch tutorial of sorts? If I happen to get to it first, I’ll document the process as well and credit you. I just don’t think there’s a clearly document d start to finish tutorial for this procedure and I think it’s very much needed.

@312Elements Thanks for looking at it. And I’d be happy to build a more complete walkthrough, see below. I run a few different Pi endpoints around the house, most of them are running Ropieee with the official 7" Pi screen and HifiBerry HATs, so nothing really different or special there. For my tinkering streamers, I alternate between these types:

  • RoonBridge running a simple kiosk display showing Roon’s Display (connecting to port 9330 on Roon), with a flip clock screensaver
  • RoonBridge running Roon Extensions and the Web Controller, a nice aftermarket interface that allows me to start/stop the music from the streamer (something I can’t do with Roon display), with a flip clock screensaver
  • Volumio, just for testing every few months to see how it’s going with Roon support. I really like Volumio and would probably swap out to Volumio on all of my Pi Roon endpoints so the fam could walk up to any and change the music/source to anything they’d like. I could do this today with volroon but I have a few small issues here and there when testing it so I don’t think it’s 100% stable yet. And of course getting Peppy support for Roon as I mentioned above. :slight_smile:

Here’s my straightforward walkthrough of the 2nd option, RoonBridge using Web Controller and a 3.5 TFT screen with USB out to a stand-alone DAC (like the Schiit Modi). It’s the most involved so if you want to use Roon’s Display instead just skip all of the steps I’ve listed as [OPT] below and change the Chrome Kiosk URL to the one that’s published in Roon’s Display settings. Hope this helps, feel free to ping me with any questions or issues, and always open to doing things more simply or different for ease and stability.

* install and update buster (raspberryPiOS 32b)
* `sudo raspi-config` to expand local storage, set timezone, and set audio to USB
* install/config screen:
  * git clone (docs, (MHS3528)
  * sudo ./MHS35-show 180
* Calibrate screen (and install unclutter while you're there)
  * apt install xinput-calibrator unclutter
  * export DISPLAY=:0 && xinput_calibrator
* install ALSA (if not installed) 
* install Roon bridge - wget
  * chmod 755 ./ && ./
* [OPT] install docker - wget -O
* [OPT] install Roon extensions - wget
* [OPT] In Roon, install extension snapshots (extensions -> system -> snapshots)
* [OPT] In Roon, install web controller (snapshots -> web/controll -> web control), then start it
* Test chromium-browser: 
  * export DISPLAY=:0 && chromium-browser --noerrdialogs --start-fullscreen --start-maximized --disable-infobars --homepage http://localhost:8080
    * Or swap out --homepage URL for Roons Display address
* add to ~/.config/lxsession/LXDE-pi/autostart to run at boot
  @unclutter -idle 0.5 -root &
  @lxpanel --profile LXDE-pi
  @pcmanfm --desktop --profile LXDE-pi
  @xset -dpms
  @chromium-browser --kiosk --no-first-run --fast --fast-start --noerrdialogs --start-fullscreen --start-maximized --disable-infobars --homepage http://localhost:8080&
* install x11-apps: sudo apt install x11-apps
  * apt install xscreensaver xscreensaver-data-extra xscreensaver-gl-extra
* install flip clock: 
  * sudo apt-get install build-essential libsdl1.2-dev libsdl-ttf2.0-dev libsdl-gfx1.2-dev libx11-dev
  * git clone
  * cd gluqlo && make && sudo make install && sudo cp gluqlo /usr/local/bin
* Add screensaver to ~/.config/systemd/user/xscreensaver.service
  ExecStart=/usr/bin/xscreensaver -nosplash
* systemctl —user enable screensaver
* Add gluqlo to local xscreensaver by adding this block at the end of the `programs:` section, removing -w and -h if you don't need to run a custom size)
  * -				gluqlo -root -ampm -w 800 -h 480	    \n\
* Run `xscreensaver` to disable everything except gluqlo
  * You'll need to ssh into the streamer with port forwarding enabled and
    using a local X server like XQuartz, or do it manually via local config
* [OPT] install shairport - apt install shairport-sync
  * edit /etc/shairport[?].conf to select correct audio device and set name
    * alsa = {output_device = "hw:1"}

Once everything is working with Roon to stream to the endpoint and display one of the options via the screen, you can pick up my two posts above to swap out chromium-browser with PeppyMeter if you’d like. My next test is to replace gluqlo with PeppyMeter and run it as the screensaver with the Web Controller, assuming you can run pygame via xscreensaver, TBD.

I’ve been running with this setup for a few weeks and generally everything is working really well. I have bumped into two minor issues, though, and would love to see if anyone has seen this?

  1. After running for a full day-ish (maybe after two days) of grouping the alsasound endpoint with the Cambridge, Roon starts to interpret pause as “Next Track”. This happens in both the Roon client as well as using the pause button directly on the Cambrdige. When I press Pause on either it just goes to the next track, and the following is displayed in logs (vumeters-lo-1 is the alsasound loopback):
04/08 17:19:50 Trace: [vumeters-lo-1] [Lossless, 16/44 MQA TIDAL FLAC => 24/44] [1% buf] [PLAYING @ 4:44/4:46] This Twilight Garden - The Cure
04/08 17:19:50 Debug: [raat/tcpaudiosource] connecting to
04/08 17:19:50 Debug: [raat/tcpaudiosource] connected
04/08 17:19:50 Warn: [raat/tcpaudiosource] send failed: Broken pipe
04/08 17:19:50 Warn: [raat/tcpaudiosource] disconnecting + retrying
04/08 17:19:50 Debug: [raat/tcpaudiosource] disconnecting

I haven’t narrowed it down to only happening when it’s playing Tidal, or maybe MQA, that’s as far as I’ve gotten.

  1. When I group the Cambridge with the alsaloop endpoint, the Cambridge will start reporting a lot of clipping which it never does when not grouped with this endpoint or when grouped with other endpoints in the house:

Screen Shot 2023-04-09 at 9.42.28 AM

Full signal path for the Cambridge when clipped:

I’ve enabled headroom and experimented down to 6 with the same result. Is there another setting in the alsaloop endpoint that could be causing this? Interestingly I always have headroom set at 4 for the Cambridge, but when I group it with the alsaloop endpoint I can audibly here the volume of the Cambridge going up, like Roon is interpreting a different headroom for the Cambridge when it’s solo and then when it’s grouped.

Let’s see your parametric EQ resulting curve!

TLDR, how do you handle different sample rates/bit depths for the vu meters zone?

Volume leveling settings need to be set every time you ungroup/regroup zones, so that’ll explain you hearing volume changes, maybe?

I’m not sure how to find/show a resulting EQ graph?

Good catch on volume leveling; I have it set to Auto for the Cambridge and not enabled for alsaloop. Once I enabled it for alsaloop and for the grouping the volume issue went away. Thanks for the pointer!

I don’t have max sampling rates or max bits per sample option for the alsaloop device. Both the Cambridge and the Cambridge+alsaloop groupings are set to allow 192kHz.

The white curve in my example is the resulting EQ curve.