Modified USB sound card

I2S and USB Sound Card

Short review: Testing I²S

The Raspberry Pi Zero doesn't have an audio jack and I previously thought I could use I²S (“Inter-IC Sound”) with a MAX98357A 3W I2S amplifier breakout to play audio files. The breakout decodes I²S digital stereo audio into an analog mono signal and amplifies it directly into a speaker. I had first made some simple I²S tests without an SPI device connected. Adafruit provides a detailed setup guide and an installation script. I just followed the instructions...

Wiring diagram
Wiring diagram: Connecting MAX98357A 3W I2S amplifier with speaker to Raspberry Pi Zero
Wiring diagram
Wiring diagram: Connecting MAX98357A 3W I2S amplifier with speaker to Raspberry Pi Zero

Installation of i2samp and mpg123

For the tests I had prepared some simple short audio files in MP3, WAV and OGG formats and copied them to the Raspi. I had been looking for audio players that could be started from a Python script, and for my initial tests I used mpg123 in a subprocess.

Note: These were my first attempts, later I used PyGame Audio Mixer to play audio files.

# Run Adafruit's install script:
sudo ./i2samp.sh
# Reboot, run it again and reboot again. Then:

# install the mp3 player:
sudo apt-get install mpg123

# And finally run the test script (example below):
python3 test.py

Simple Python script with mpg123 in subprocess

This was one of my first minimalist test scripts for playing some sound files...

#!/usr/bin/python3

# Import libraries
import subprocess
import time

# Play first audio file for 2 seconds
player = subprocess.Popen(["mpg123",  "sounds/01.mp3", "-q"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
time.sleep(2)
# ... then the second audio file for 2 seconds
player = subprocess.Popen(["mpg123",  "sounds/02.mp3", "-q"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
time.sleep(2)
# ... (some more audio files)

# Stop and reset (not sure if I used this or not, it was commented out in my last backup of the test script)
#player.stdin.write("pause")
#player.stdin.flush()

USB audio card as a replacement for I2S

I²S audio requires the use of GPIO21 on the Raspberry Pi (I²S data out). This GPIO is also used for SPI1 SCLK (clock), as I already noticed some time ago when I draw a wiring diagram for my test setup. As far as I know it is not possible to use both I²S and SPI1 in parallel, you can only use either one or the other.

Since I wanted to use SPI1 for the LED breakout board, I looked around for audio alternatives and came across the PCM2704 USB Sound Card. I ordered a couple of those small, cheap circuit boards, removed the USB connector and soldered wires to it instead, as well as to the 3.5mm audio jack (those awful looking solder joints were only temporary for my test setup).

I had also ordered the TPA2012 Stereo 2.1W Class D Audio Amplifier, which allows my to use two speakers for stereo sound (although I don't think you'll notice much of that once the speakers are installed in the case). Below is a wiring example for my audio test setup.

All boards are conneted to the 5V power supply and common ground. The USB data lines are connected to the USB test pins on the back of the Raspi. I used cables with connectors in my test setup so that I can remove the USB sound card at any time and connect a USB keyboard, for example, if I need to.

Wiring diagram
Wiring diagram: Connecting PCM2704 USB sound card, TPA2012 Audio Amp and speakers to Raspberry Pi Zero
Wiring diagram
Wiring diagram: Connecting PCM2704 USB sound card, TPA2012 Audio Amp and speakers to Raspberry Pi Zero

Setting USB audio as default

Note: These steps are related to an older Raspberry OS, the settings may no longer be necessary.

I thought/hoped the USB Sound Cards works with “plug and play” and you don't have to install anything manually. Unfortunately, the sound card did not play sound files immediately when I rebooted the Raspberry Pi. In my first tests I just entered sudo aplay test.wav in the Terminal/Console.

To check if the USB device is recognized by Raspi at all, I entered

lsusb

The result showed that the USB device was recognized, but apparently it was not addressed by the system for audio output. After some research I found a forum thread about setting USB audio as default in Raspbian. To do so, you first have to determin the card number of the USB device:

aplay -l

Or if you want to get more detailed results:

aplay -L

In my setup the USB Sound Card had the card number 2. To change the default audio device, I first made a backup (copy) of the alsa configuration file /usr/share/alsa/alsa.conf:

# change to alsa directory:
cd /usr/share/alsa
# copy the config file:
sudo cp alsa.conf alsa.conf.orig

Then I edited the file /usr/share/alsa/alsa.conf with the nano editor:

# Open the file in the nano editor:
sudo nano alsa.conf

...and changed the card numbers of these two lines:

defaults.ctl.card 0
defaults.pcm.card 0

... to this (card number 2):

defaults.ctl.card 2
defaults.pcm.card 2

Then I saved the file, quit the nano editor and rebooted.

After reboot I entered sudo aplay test.wav again and the USB sound card finally worked, I heard the sound through the small speaker.

I continued to test different media players to play a sound file from a Python script, and adjusted the gain settings (dB) of the TPA2012 Audio Amp to achieve a satisfactory volume with my test speakers...