Pico-USB-audio
This library streams Audio over USB to Raspberry Pi Pico microcontrollers. It then uses a 4th order pulse density modulator to output audio through the Pico's Programmable Input Outputs (PIO). It only requires two resistors and two capacitors to output pretty good audio. Check out the video below.
Table of contents
Preface
There are a couple of things to be aware of when using this library.
- It underclocks (115.2 MHz for 32 X oversampling) the Pico.
- Sigma delta modulaters can get unstable and produce unpleasant sounds.
- I won't guarantee this code won't blow up your favourite speakers or headphones (it shouldn't) but no guarantees.
Arduino Mbed Code
An Arduino compatible USB sound card version is available. This code uses the official Arduino RP2040 core. This greatly simplifes the install and development process. The necessary mbed files can be easily installed with the Arduino board manager. Search "mbed rp2040" and install. Install the Arduino library in your Arduino libraries folder. Then run the mbedUSB example for 32 times oversampling.
#include "pdmAudio.h"
// PDM object
pdmAudio pdm;
void setup() {
// set pin 14 to be the output
pdm.begin(14);
// intiate USB transfer
pdm.USB_UAC();
}
void loop() {
// write whatever is in the USB buffer to the PDM -DAC
pdm.USBwrite();
}
The Circuit
The Circuit is pretty simple, it is composed of A lowpass filter at bout 20 KHz and a decoupling capactitor to removed the DC offset. The Output voltage in the audible band is 1.1V peak-peak.
and in reality it looks like this.
Tones
Tones can be played in a manner similar to the Tone library for arduino.
##include "pdmAudio.h"
// PDM object
pdmAudio pdm;
void setup() {
pdm.begin(14);
}
void loop() {
//each tone is governed by a frequency and duration(seconds)
// zero frequency keeps voltage constant
pdm.tone(262, .25);
pdm.tone(0, .165);
pdm.tone(196, 0.125);
pdm.tone(0, .08);
pdm.tone(196, 0.125);
pdm.tone(0, .08);
pdm.tone(220, 0.25);
pdm.tone(0, .16);
pdm.tone(196, 0.25);
pdm.tone(0, .16);
pdm.tone(0, 0.25);
pdm.tone(0, .16);
pdm.tone(247, 0.25);
pdm.tone(0, .16);
pdm.tone(262, 0.25);
pdm.tone(0, 1);
}
USB microphones
Microphone data can be passed to the computer over USB using the following code. This test sends a 48O Hz sine wave over USB that can be monitored with a software such as Audacity.
#include "pdmAudio.h"
pdmAudio pdm;
void setup() {
pdm.USB_UAC();
}
void loop() {
// look up table sine-wave at 480 Hz
int16_t left = pdm.sine_lu(480);
int16_t right = left;
// write stereo data to computer
pdm.USBtransfer(left, right);
}
Other microcontrollers
To support microcontrollers other than the RP2040 a few things are needed.
- Fast multiplication and addition of 32-bit integers.
- A peripheral that can create precisely timed, high frequency pulses (PIO on rp2040 or I2S on other controllers).
- A mechanism of audio acquisition (USB, Bluetooth, SD card).
Currently the following features are supported for different controllers
MCU | PDM | Tones | USB | Bluetooth | CPU - 32x(%) | CPU - 64x(%) |
---|---|---|---|---|---|---|
RP2040 | βοΈ | βοΈ | βοΈ | β | 33% | 66% - 230.4 MHz |
ESP32 | βοΈ | βοΈ | β | βοΈ | 30% | 60% - 240 MHz |
ESP32-S2 | βοΈ | βοΈ | β | β | 30% | 60% - 240 MHz |
STM32 | βοΈ | β | β | β | 30% | 60% - 168 MHz |
Feather M4 | βοΈ | βοΈ | β | β | 22% | 44% - 200MHz |
Teensy 4.1 | βοΈ | β | β | β | 5% | 10% - 600 MHz |
Building for pico-sdk
Cmake and pico USB became too hard to maintain. Arduino code is now all that is supported.