How I debugged my Audioengine HD3 speakers in Linux
I purchased a pair of desktop speakers recently, the Audioengine HD3 (based on this review). On my desktop, I'm running Ubuntu; 20.10 Groovy Gorilla until recently, but 21.04 Hirsute Hippo now. The speakers worked just fine when I first got them, but somewhere along the way (I don't know exactly when, but quite possibly when I updated), I couldn't get any sound out of them, despite the system having no trouble detecting them.
With the help of my local Linux User Group, this is how we debugged the issue, and what I learned along the way. This post is structured like a bug report with all the information I thought might be relevant, in order of what was tried, but it is sprinkled with exposition and just happens to end with a solution.
When connecting my speakers, I see this in dmesg
:
usb 1-1: 1:1: cannot set freq 48000 to ep 0x3
I've been told that audio in Ubuntu (and most Linux distributions) consists of two primary layers:
- Advanced Linux Sound Architecture (ALSA), the lower layer.
- PulseAudio, the higher layer.
To restore audio, I should first make sure I can play audio through ALSA with its tools. Once that is solved, then any remaining problems can be attributed to the Pulse layer. To play audio through ALSA, I must first disable Pulse to make it release its handles to my audio devices:
systemctl --global stop pulseaudio.service pulseaudio.socket
aplay
is an ALSA tool for playing audio.
aplay -L
lists all the "devices" (in ALSA parlance) that can play audio.
Each device is actually a combination of a plugin and the hardware.
It listed 14 devices for my speakers.
(There are even more for my onboard audio, video card, and webcam).
speaker-test
is an ALSA tool for playing test audio when one doesn't have an audio file on hand.
speaker-test -D $device -c 2
makes sound with 6 of my speaker's ALSA devices, the ones with these plugins: hw
, plughw
, front
, surround40
, iec958
, dmix
.
To name the device, they are all suffixed with :CARD=HD3,DEV=0
.
Unlike speaker-test
, aplay
requires an audio file.
I generated a test audio file using ffmpeg
:
ffmpeg -f lavfi -i "sine=frequency=1000:sample_rate=48000:duration=5" \
-c:a pcm_s16le -ac 2 sine.wav
aplay -D $device -c 2 sine.wav
works when the WAV file is encoded in stereo at 48k Hz to 16 bit signed little endian (SLE), and only with those parameters.
Trying a 44.1k WAV file plays a burst of audio for a fraction of a second at the beginning of the very first attempt, and then nothing at all following or on subsequent attempts.
At this point it appears that sound is working, at 48k at least. So I enable Pulse audio:
systemctl --global start pulseaudio.service pulseaudio.socket
I see this in dmesg
:
retire_capture_urb: 39 callbacks suppressed
When I have Pulse enabled, I'm testing sound via Settings -> Sound -> Volume Levels -> Output -> Test.
pacmd list-sinks
lists Pulse "sinks" (their name for devices, which may be virtual).
It shows sample spec: s16le 2ch 44100Hz
for my speakers.
Trying this command changes the properties
list but does not affect the sample spec
:
pacmd update-sink-proplist alsa_output.$alsa_output \
format=s16le rate=48000
Editing /etc/pulse/daemon.conf
to set default-sample-rate
and alternate-sample-rate
both to 48000
and restarting Pulse (pulseaudio -k
) corrects the sample spec
, but still no sound is made.
I disable Pulse again, and find my previously working ALSA commands have stopped making sound.
I start alsamixer
, select my speakers, and see volume at 0<>100
.
Holding the Up key, I can bring the volume to 100<>100
, and sound works again.
So it seems something in Pulse is setting my volume to 0%, and there's nothing I can do in Pulse to change it.
In fact, everything I saw in Pulse showed my volume at 100%.
But unlike the other ALSA tools, I can run alsamixer
while Pulse is enabled.
So I enable Pulse, open alsamixer
, restore volume to 100%, and the speakers start making sound.
Problem solved.