RP2040 USB Sound Card (Pulse Density Modulated Audio)
by the2ndTierney in Circuits > Raspberry Pi
9361 Views, 4 Favorites, 0 Comments
RP2040 USB Sound Card (Pulse Density Modulated Audio)
I'm really intrigued by the Programmable input outputs (PIO) on the RP2040. They make it easy to create circuits that have very precise timing requirements. Audio circuits require very precise timing and seem like a good way to test the PIO. But the rp2040 can't produce audio... Or can it?
It can. It has already been shown that you can use pulse width modulation (PWM) to produce audio but there is a resolution-bandwidth tradeoff with PWM audio. I've been playing around with Pulse Density Modulated Audio which uses a complicated noise shaping algorithm and heavy oversampling (1.536MHz in this instructable) to create high-quality audio. I've adapted some USB code from the pico-playgrounds examples to enable you to stream audio directly to the RP2040 from your computer. The RP2040 then does some magic noise shaping and uses the PIO to produce the audio without a DAC (see video above and then build it yourself because my recording quality is always rubbish).
The modulator algorithm is a 4th order software modulator of my own design and, for a £4 microcontroller, sounds pretty damn good (to my ears). This instructable won't cover the theory or code but will show you how to get up and running. I've wrapped this up into an Arduino .ino file and made the pico-SDK source available on my Github.
Supplies
- RP2040 based microcontroller
- USB cable
- 1 x 220-ohm resistor
- 1 x 3900 ohm resistor
- 1 x 10 microfarad capacitor
- 1 x 33 nanofarad capacitor
- 1 headphone jack
- AUX cable
- jumper wires
- Speakers
The Circuit
The circuit is essentially the same as the recommended raspberry pi audio circuit (see in hardware design datasheet and this blogpost and comments). The main difference is I don't use the resistor divider to bring the voltage down to 1V peak to peak. This is taken care of in software. I also just used the capacitors I had that were closest in value. If you want better bass on headphones you might need to increase the value of C2 to 47 microfarads. This shouldn't matter for line out. The low pass filter has a slightly lower capacitor value but that is to compensate for the fact that in the raspberry pi design the resistor divider lowers the effective resistance and therefore needs a bigger capacitor for the same frequency response.
Uploading the Code - Arduino and PICO-SDK
To build using the Arduino IDE is simple.
- In the Board manager, download the official Arudino mbed library for RP2040.
- download this .ino sketch and pio.h file and upload it to your board.
To build on the pico SDK.
- Hold down the bootsel button on your rp2040 as you plug in your USB. This will cause the rp2040 to appear as a USB drive on your computer.
- . Drop the UF2 file into the drive and you should see the pico sound card appear on as one of your sound devices (tested on windows).
Currently, sampling rates of 48Khz are all that are supported. I also slightly underclock the RP2040 (115.2 MHz) to get the audio timing just right. You could also overclock to 153.6 MHz, 192MHz, 230.4MHz, or 268.8MHz but that's currently unnecessary. You could also build this from source but the documentation and the interface to the library is very much a work in progress.
Future Steps
This project is nowhere near complete but it is functional, on windows, at 48Khz, in Mono using both the arduino IDE and the pico-sdk. Some improvements I hope to make are
- make it stereo (currently averages left and right channels)
- make it run > 3Mhz (will further improve audio quality)
- add automatic interpolation to 48 KHz from 44.1 KHz (support more devices)
- explore different feedback algorithms (hopefully improve computational efficiency)
But anywho, that is enough for now. Hope you enjoy the music.