HomeRaspberry Pi › Volume
 

Raspberry Pi Volume Control

Adjust the Alsa soundcard volume of your Raspberry Pi computer from the command line. Normally this can be done by amixer cset numid=1 -- number where number is a whole number (integer) between something like -10200 and +400 in centi-dB units (mB, I guess). For me, it would be easier to adjust it as a percentage from 0 (mute) to 100 (maximum). This is a script to make that possible. Save the code to a text file in your path and make it executable like so:

sudo nano /usr/local/bin/vol
# Type or paste the code from below into the editor
Ctrl-x, y, Enter   # Keystrokes to leave the editor while saving the file
sudo chmod a+x /usr/local/bin/vol

Use the vol script like so:

vol     # Outputs the current volume as a number between 0 and 100
vol +   # Turn up the volume by 3
vol -   # Turn down the volume by 3
vol 85  # Set the volume to 85

You may use a different +/- adjustment step by changing the ADJ variable near the top of the script (see below). You may also set a maximum volume lower than 100 to prevent distortion, by changing the HI variable. Set it to 95, for example. Similar for LO to avoid inaudible output. If you are not logged in as the standard user pi and nothing works, it may be because you are not a member of the audio group. Fix like so: sudo adduser `whoami` audio

The Code

#!/bin/bash

MIX=amixer
declare -i LO=0     # Minimum volume; try 10 to avoid complete silence
declare -i HI=100   # Maximum volume; try 95 to avoid distortion
declare -i ADJ=3    # Volume adjustment step size

usage ()
{
	echo "Usage: `basename $0` [ - | + | N ]" >&2
	echo "  where N is a whole number between $LO and $HI, inclusive." >&2
	exit 1
}

# Zero or one argument
[ $# -le 1 ] || usage

# Argument must be one of: empty, -, +, number
[[ $1 == ?(-|+|+([0-9])) ]] || usage

ARG="$1"

# Number argument
if [[ $ARG == +([0-9]) ]]; then
	# Strip leading zeros
	while [[ $ARG == 0+([0-9]) ]]; do
		ARG=${ARG#0}
	done
	# Must be between LO and HI
	(( ARG >= LO && ARG <= HI )) || usage
fi

EXE=$(which $MIX)
if [ -z "$EXE" ]; then
	echo "Error: $MIX not found. Try \"sudo apt-get install alsa-utils\" first." >&2
	exit 2
fi

GET=$($EXE cget numid=1)
declare -i MIN=$(echo $GET | /bin/grep -E -o -e ',min=[^,]+' | /bin/grep -E -o -e '[0-9-]+')
declare -i MAX=$(echo $GET | /bin/grep -E -o -e ',max=[^,]+' | /bin/grep -E -o -e '[0-9-]+')
declare -i VAL=$(echo $GET | /bin/grep -E -o -e ': values=[0-9+-]+' | /bin/grep -E -o -e '[0-9-]+')

if (( MIN >= MAX || VAL < MIN || VAL > MAX )); then
	echo "Error: could not get the right values from $MIX output." >&2
	exit 3
fi

declare -i LEN=0
(( LEN = MAX - MIN ))

declare -i ABS=0
(( ABS = VAL - MIN ))

declare -i PCT=0
(( PCT = 100 * ABS / LEN ))

if [ ! -z "$ARG" ]; then

	declare -i OLD=$PCT

	if [[ "$ARG" == "+" ]]; then
		(( PCT += ADJ ))
	elif [[ "$ARG" == "-" ]]; then
		(( PCT -= ADJ ))
	else
		PCT=$ARG
	fi

	if [[ "$PCT" != "$OLD" ]]; then
		(( ABS = PCT * LEN / 100 ))
		(( VAL = MIN + ABS ))
		$EXE -q cset numid=1 -- $VAL
	fi
fi

echo $PCT
exit 0