10-10-2022, 10:43 PM
(This post was last modified: 10-11-2022, 08:44 PM by roderickvd.)
The human ear is not equally responsive across the audio range. It is more sensitive to mid-frequencies than to the lower and higher frequencies. This situation becomes more pronounced at low volume levels. This is exactly what a loudness compensated volume control does: the more the volume is turned down, the more the bass and treble are boosted so it sounds the same.
This post shows how to implement such a volume control for a wide variety of audio renderers by using the Alsa dummy driver and the wonderful CamillaDSP that are all aboard on moOde already. The working principle is that the renderers set their volume in the dummy's mixer, which we continuously monitor with a script called dummyvol2cdsp, and forward to CamillaDSP using a websocket. And with this guide, it should sound more complicated than it really is :-)
You must have SSH enabled and know your way around the command line.
Set up Alsa dummy driver
First, set up the Alsa dummy driver. Later we will use its mixer control as a proxy to CamillaDSP's volume filters.
Note: although we do not need any of the dummy's PCM streams or substreams, do not set them to 0. Doing so will cause the system to hang on reboot, and you will need to reinstall or recover on another system.
Optional: make the dummy mixer control the system-wide default. This helps to immediately show the dummy mixer controls with amixer and alsamixer, for example.
Note: the dummy driver should register as card 0 because it is registered first when booting. If it does not, use aplay -l to find out the right card number after rebooting.
Now reboot and verify that the dummy driver is set up correctly:
Set up CamillaDSP loudness filters
Now at the other end of the chain we add volume filters to CamillaDSP. You can use a Volume filter or a Loudness filter. The loudness filter in fact is a volume filter, but with extra parameters and functionality to apply loudness correction when the volume is lowered.
The relevant configuration lines are as follows. Read on on how to configure this via the web interface.
A few notes on these values:
CamillaDSP is now ready to get its volume settings over a websocket. We will get to that later.
Set up audio renderers
Warning: during this step turn your amplifier off! Risk of damage and/or injury!
If you start playback, it will output at full volume and the volume slider will do nothing yet!
AirPlay:
Change the following lines in /etc/shairport-sync.conf. The lines are commented by the default, uncomment them.
Note: although the dummy device mixer registers as a hardware mixer, it does not support hardware mute. Keep use_hardware_mute_if_available set to no.
Spotify:
Edit /var/www/inc/renderer.php. The first line you have to change, the second you have to add immediately after:
Note: moOde version updates may overwrite this. If so, change it again.
MPD:
I do not use MPD so am not certain. But editing /etc/mpd.conf like this should do it:
Note: moOde audio setting changes overwrite this. If so, change it again.
Bluetooth:
Not supported yet. It requires bluez-alsa v4.0.0 or higher: https://github.com/Arkq/bluez-alsa/pull/390 and moOde 8.2.1 has v3.0.0. In the meantime its software volume control works fine, just not with loudness correction.
Others:
Unknown, I do not use them. But if you find out, drop a reply and I will add it to this post!
Set up dummyvol2cdsp
dummvol2cdsp is a Python script that runs in the background, monitoring the dummy mixer control and forwards its volume setting to CamillaDSP over a websocket. It also provides a cubic volume control to maximise the usable range of the volume sliders.
First install the pyalsaaudio library:
Now download `dummyvol2cdsp.py` from https://github.com/roderickvd/dummyvol2cdsp and put it somewhere. This guide assumes /home/pi/dummyvol2cdsp.py. At the top of the script, there are some user-configurable settings. The defaults should be sane.
Don't forget to make the script executable, then launch it to start testing:
Open another terminal, launch alsamixer and change the volume. You should now see the script printing lines like alsa=49% cubic=-50.5 dB. If it also prints along the lines of setting cdsp volume failed: [Errno 111] Connection refused, that means that CamillaDSP is not running yet. A likely cause is that playback has not started yet (regardless of whether an audio renderer is connected or not).
If you see volume settings being printed without errors, then look at the CamillaDSP GUI via the web interface and change the volume again. Under Volume at the left, you should see the volume changes coming in.
Now everything is working, hit Ctrl+C to exit. Then edit /etc/rc.local to launch dummyvol2cdsp in the background when booting. The following lines should just be before the final exit 0 at the bottom:
Note: moOde version updates may overwrite this. If so, add it again.
Finally, reboot and verify that volume changes are still being forwarded to CamillaDSP.
If you have convinced yourself volume changes are coming in properly, you can now turn up the amplifier again -- in small steps, just as a final precaution. Congratulations, you have yourself a working loudness-corrected volume control!
FAQ
Q: Which volume type should I set in moOde's audio configuration? Hardware, software, anything else?
A: For the supported renderers I do not think it really matters. Principally the dummy driver is a hardware control, but it is not related to the output device. MPD should be set to hardware, but still overwrites the mixer device with the output device instead of the dummy device.
Q: How do I use my DAC's hardware volume control then?
A: You cannot. CamillaDSP does this in software only. Here is the good news: sound-quality wise, that will the best. CamillaDSP uses a 64-bit floating point pipeline which is better than any DAC does in hardware. Then running your DAC at full line level will improve dynamic range to your amplifier (unless the connection is balanced, in which case it will not matter). You may only miss out on fancy readings from your DAC's display or comfort of using your DAC's remote.
If anyone has any tips or tricks to share, please reply and I will add it to this post.
This post shows how to implement such a volume control for a wide variety of audio renderers by using the Alsa dummy driver and the wonderful CamillaDSP that are all aboard on moOde already. The working principle is that the renderers set their volume in the dummy's mixer, which we continuously monitor with a script called dummyvol2cdsp, and forward to CamillaDSP using a websocket. And with this guide, it should sound more complicated than it really is :-)
You must have SSH enabled and know your way around the command line.
Set up Alsa dummy driver
First, set up the Alsa dummy driver. Later we will use its mixer control as a proxy to CamillaDSP's volume filters.
Code:
# sudo su -
# echo "options snd-dummy fake_buffer=0 pcm_substreams=1" >> /etc/modprobe.d/snd_dummy.conf
# echo "snd-dummy" >> /etc/modules-load.d/modules.conf
Optional: make the dummy mixer control the system-wide default. This helps to immediately show the dummy mixer controls with amixer and alsamixer, for example.
Code:
# echo "defaults.ctl.card 0" >> /etc/alsa/conf.d/00-defaults.conf
# chmod a+x /etc/alsa/conf.d/00-defaults.conf
Now reboot and verify that the dummy driver is set up correctly:
Code:
# reboot
# aplay -l
**** List of PLAYBACK Hardware Devices ****
card 0: Dummy [Dummy], device 0: Dummy PCM [Dummy PCM]
Subdevices: 1/1
Subdevice #0: subdevice #0
card 1: ...
# amixer scontrols
Simple mixer control 'Master',0
Simple mixer control 'Synth',0
Simple mixer control 'Line',0
Simple mixer control 'CD',0
Simple mixer control 'Mic',0
Simple mixer control 'External I/O Box',0
Set up CamillaDSP loudness filters
Now at the other end of the chain we add volume filters to CamillaDSP. You can use a Volume filter or a Loudness filter. The loudness filter in fact is a volume filter, but with extra parameters and functionality to apply loudness correction when the volume is lowered.
The relevant configuration lines are as follows. Read on on how to configure this via the web interface.
Code:
devices:
chunksize: 1024
queuelimit: 1
filters:
loudnessvol:
type: Loudness
parameters:
ramp_time: 200.0
reference_level: -10.0
high_boost: 3.0
low_boost: 8.5
pipeline:
- type: Filter
channel: 0
names:
- loudnessvol
- type: Filter
channel: 1
names:
- loudnessvol
A few notes on these values:
- Recommended values for chunksize are 1024 for 44.1/48 kHz, 2048 for 88.2/96 kHz, 4096 for 176.4/192 kHz, and so on.
- A queuelimit of 1 ensures the lowest audio latency to user input.
- The ramptime gently increases or decreases the volume for the given duration in milliseconds. This prevents popping noises that could by caused by abrupt volume changes. 200 milliseconds is a sane default.
- The reference_level very much depends on your audio chain, source material and personal preferences. You may try values between 0 and 30.
- The high_boost and low_boost were chosen as averages from the ISO 226 equal-loudness contours. Again this depends on your needs and preferences, and plays along with the chosen reference_level.
- If you have other mixers or filters, loudnessvol should be last in the pipeline.
- Only if your output device is limited to 16-bit audio, you may choose to add a Dither filter after loudnessvol in the pipeline.
- Edit the CamillaDSP settings.
- Under Pipeline configuration, create a New one or Copy one you will use as foundation. (*)
- Under General, select the desired pipeline configuration from the drop-down list and Save to make it active.
- Under Pipeline editor, set Status to On.
- Under Pipeline editor, Open the pipeline editor.
- If you only see the menu and "Pipeline editor" header, reload your browser as the GUI was still starting.
- In the Devices tab, set the chunksize and queuelimit.
- In the Filters tab, press the green + sign at the bottom to add the loudnessvol filter and its parameters.
- In the Pipeline tab, press the green + sign at the bottom to add the loudnessvol filter to the pipeline for channel 0.
- Repeat to add the loudnessvol filter to the pipeline for channel 1.
- If necessary, drag & drop the two loudnessvol filters to be at the bottom (end) of the pipeline.
- Under Config at the left, Save to file or if possible Apply and save (only available when already running).
CamillaDSP is now ready to get its volume settings over a websocket. We will get to that later.
Set up audio renderers
Warning: during this step turn your amplifier off! Risk of damage and/or injury!
If you start playback, it will output at full volume and the volume slider will do nothing yet!
AirPlay:
Change the following lines in /etc/shairport-sync.conf. The lines are commented by the default, uncomment them.
Code:
mixer_control_name = “Master”;
mixer_device = "hw:Dummy”;
Spotify:
Edit /var/www/inc/renderer.php. The first line you have to change, the second you have to add immediately after:
Code:
' --mixer alsa' .
' --alsa-mixer-device hw:Dummy --alsa-mixer-control Master' .
MPD:
I do not use MPD so am not certain. But editing /etc/mpd.conf like this should do it:
Code:
audio_output {
...
mixer_type "hardware"
mixer_control “Master”
mixer_device "hw:Dummy”
mixer_index "0"
...
}
Bluetooth:
Not supported yet. It requires bluez-alsa v4.0.0 or higher: https://github.com/Arkq/bluez-alsa/pull/390 and moOde 8.2.1 has v3.0.0. In the meantime its software volume control works fine, just not with loudness correction.
Others:
Unknown, I do not use them. But if you find out, drop a reply and I will add it to this post!
Set up dummyvol2cdsp
dummvol2cdsp is a Python script that runs in the background, monitoring the dummy mixer control and forwards its volume setting to CamillaDSP over a websocket. It also provides a cubic volume control to maximise the usable range of the volume sliders.
First install the pyalsaaudio library:
Code:
# sudo su -
# pip install pyalsaaudio
Now download `dummyvol2cdsp.py` from https://github.com/roderickvd/dummyvol2cdsp and put it somewhere. This guide assumes /home/pi/dummyvol2cdsp.py. At the top of the script, there are some user-configurable settings. The defaults should be sane.
Don't forget to make the script executable, then launch it to start testing:
Code:
# chmod a+x /home/pi/dummyvol2cdsp.py
# /home/pi/dummyvol2cdsp.py
Open another terminal, launch alsamixer and change the volume. You should now see the script printing lines like alsa=49% cubic=-50.5 dB. If it also prints along the lines of setting cdsp volume failed: [Errno 111] Connection refused, that means that CamillaDSP is not running yet. A likely cause is that playback has not started yet (regardless of whether an audio renderer is connected or not).
If you see volume settings being printed without errors, then look at the CamillaDSP GUI via the web interface and change the volume again. Under Volume at the left, you should see the volume changes coming in.
Now everything is working, hit Ctrl+C to exit. Then edit /etc/rc.local to launch dummyvol2cdsp in the background when booting. The following lines should just be before the final exit 0 at the bottom:
Code:
# Forward Alsa dummy mixer volume to CamillaDSP
/home/pi/dummyvol2cdsp.py > /dev/null 2>&1 &
Finally, reboot and verify that volume changes are still being forwarded to CamillaDSP.
If you have convinced yourself volume changes are coming in properly, you can now turn up the amplifier again -- in small steps, just as a final precaution. Congratulations, you have yourself a working loudness-corrected volume control!
FAQ
Q: Which volume type should I set in moOde's audio configuration? Hardware, software, anything else?
A: For the supported renderers I do not think it really matters. Principally the dummy driver is a hardware control, but it is not related to the output device. MPD should be set to hardware, but still overwrites the mixer device with the output device instead of the dummy device.
Q: How do I use my DAC's hardware volume control then?
A: You cannot. CamillaDSP does this in software only. Here is the good news: sound-quality wise, that will the best. CamillaDSP uses a 64-bit floating point pipeline which is better than any DAC does in hardware. Then running your DAC at full line level will improve dynamic range to your amplifier (unless the connection is balanced, in which case it will not matter). You may only miss out on fancy readings from your DAC's display or comfort of using your DAC's remote.
If anyone has any tips or tricks to share, please reply and I will add it to this post.