A cheap UAC 1.0 in to UAC 2.0 out converter that allows your PS5, switch, etc to use high end speakers

Hi, I would like to share my recent work: a cheap USB Audio Class 1.0 (UAC) input to UAC 2.0 output converter.

What the hack is UAC 1.0, 2.0, and this crazy thing?

For folks that may not understand why I have this crazy idea, here is the background:

For some shitty reasons, PS5 does not support outputting audio through certain USB sound card, and that is because PS5 only supports very old USB sound card (UAC 1.0), and usually high end speakers or sound cards would use newer, better UAC 2.0 protocol.

So, this shitty thing happens to me, when I thought my EDIFIER S880 speaker would be a plus for my gaming experience. EDIFIER S880 has a UAC 2.0 in input source, so my PS5 does not support that. So, what I can do is to use another 3.5 jack to connect the speaker to my PS5.

Unfortunately, there is a staticky buzz sound throughout this channel. What’s even worse is that EDIFIER S880 has 6 input source selection, but I can only switch to the next source, wait for 2 seconds, and repeat this process 5 times every time I want to switch the audio from my computer to the PS5.

Idea

The idea is to use a board that has 1 USB otg port to act as a UAC 1.0 sound card, and has another 1 USB host port to connect to the UAC 2.0 speakers, then run programs on that board to redirect sound from USB otg port to USB host port. It is even a plus that the board consumes less power, so we do not need an extra or special power supply for it; this becomes crucial, especially when sharing the same USB connection with the USB otg port (SBC boards are more power-hungry these days!). The standard USB 2.0 protocol only allows 5V 0.5A to the device connected.

I actually built one with an Orange Pi One board, but it turns out that the CPU is not fast enough, and there are sound glitches sometimes.

Board selection

With some research, I found this board that perfectly fits my needs: Radxa zero 3W. Here is the advantage:

  • It is cheap, and the one I used is the nearly minimum SKU (1 GB ram with 8 GB onboard eMMC, they also have no onboard eMMC SKU).
  • The otg port could handle USB PD protocol, meaning no special hacks are needed, you could get at most 30W of power, if needed (and turns out the normal USB 2.0 port on my PS5 works perfectly, so I guess it consumes less than 5V 1A = 5W)
  • It is tiny.

Painful (?) development

However, things don’t work right out of the box. At the beginning, I flashed the official, latest Radxa OS, modprobe the g_audio. It is running as a UAC 2.0 device, so it is not the one I want. As a result, I grabbed their kernel source, changed the config to UAC 1.0 gadget, and flashed onto the board, but there seems to be some issues in their kernel fork for UAC 1.0 driver: there was no /dev/snd/controlC0, so the g_audio failed to run.

As a result, I turned to use the Armbian build. This time, the /dev/snd/pcmC0D0c is missing, so g_audio failed to run again.

I then compiled my own kernel, flashed it onto the board. The Armbian build is with kernel 6.1, and the kernel I built is kernel 6.12, then the board failed to boot to the kernel due to U-Boot thought there were some errors.

Luckily, I found that building the whole Armbian image with kernel 6.12 can boot without issues, so I built a custom kernel 6.12 with UAC 1.0 enabled image, modeprobe the g_audio module, and it finally worked!

After that, I crafted a simple golang SystemV daemon for bootstrapping and terminating the alsaloop program for redirecting the sound, and used a udev rule to notify that daemon of the attachment/detachment of the USB speaker out event. The converter is finally working!

Prebuilt to share

Here is the pre-built image for folks who want a quick test. It is based on the commit b27c86e620dcd9f55daadf52ccc85643dba2a381 from the armbian build repo with the following config modification:

diff --git a/config/kernel/linux-rockchip64-current.config b/config/kernel/linux-rockchip64-current.config
index d053d0997..6e360bba7 100644
--- a/config/kernel/linux-rockchip64-current.config
+++ b/config/kernel/linux-rockchip64-current.config
@@ -3507,3 +3507,8 @@ CONFIG_RATIONAL_KUNIT_TEST=m
 CONFIG_MEMCPY_KUNIT_TEST=m
 CONFIG_TEST_MEMCAT_P=m
 CONFIG_MEMTEST=y
+
+CONFIG_USB_CONFIGFS_F_UAC1=y
+CONFIG_USB_CONFIGFS_F_UAC2=n
+CONFIG_USB_F_UAC2=n
+CONFIG_GADGET_UAC1=y

Currently, the “current” build does not detect the Wi-Fi interface, but as it does not affect the audio converting feature, I may not put too much effort into this.

Hi brother, this work of yours is amazing and I would like to do something similar to this too. However, I am not a developer and I do not know anything about coding but I need this project and ready to put my time and learn stuff.

My requirement is to get the audio from ps5 (UAC 1) and route that audio to my USB dongle DAC (UAC 2)

I can get this somehow. But could you guide me how to go further from there?

My USB dongle dac

Sure, but I am a little bit busy recently, so I will share some key points here that you can try right away.

  1. After flashing the pre-built image I shared, you can use modprobe g_audio, it will make the USB otg port become a UAC 1.0 device right away.
  2. Next, you can run alsaloop to redirect the sound from the otg device source to the output speaker. The full command is alsaloop -C hw:CARD=UAC1Gadget,DEV=0 -P <speaker card name> -t 10 -A 0 -S 5 -b.
    You will need to find the <spekaer card name> of yours, and you can list all sound card via aplay -L.
  3. At this point, you will have a working UAC 1.0 to UAC 2.0 converter. You can also use alsamixer to adjust the output volume.

I did some more work to automatically bootstrap the alsaloop command (for finding the speaker card name automatically when UAC 2.0 speaker is inserted, and terminating the alsaloop when UAC 2.0 speaker is detached).

1 Like

@lschyi https://github.com/SaneBow/PiDTLN works pretty good on a PiZero2 should have no probs on a Rock3W. The DTLN filter is lighter and less glitchy than the AEC model.
Its Tflite and for those how want to game but use a microphone it could be useful and might make a great addition.
You sound like you know your audio dev, PS as an afterthought https://www.seeedstudio.com/ReSpeaker-Lite-p-5928.html as xmos have libs for UAC audio but its not been implemented and been wondering if hardware, that the USB is hard connected to a uart convertor so can not have dual use and the USB pins are not avail… Maybe its just software and it opens up some interesting use?!? Xmos seem to have the libs https://github.com/xmos/lib_xua
Some might like to be headfree than headset and that DTLN doesn’t like ‘Doubletalk’ but its considerably lighter than say https://github.com/Rikorose/DeepFilterNet that needs a much bigger single core than that of a RK3588. Xmos would be your soundcard with mics onboard and an extra layer as its much less than literature would make you believe…
Anyway great work as its sort of nuts that the PS5 Orbis OS is a far removed, some flavour of FreeBSD. That in that respect totally voids any warranty but also a substantial effort is needed.

Thanks for your reply. Whenever you are free please help me with few more information

  • Does it run hot while gaming? do we need an enclosure or some type of heat management in place?

  • How do I flash the pre-built image? I am also simultaneously googling around, I hope I find some answers on my own…

  • Does it preserve the audio quality from the PS5 or does it alter the audio? I mean, it just acts as a Uac 1 to route audio from one source to another right? No decoding in between? Because I want my dac to handle all the decoding stuff.

  • Does it run hot while gaming? do we need an enclosure or some type of heat management in place?

Yes, but a regular heat sink is good enough. During my test, I saw some glitches when the CPU was very hot. However, after applying a regular heat sink, I have never seen a glitch.
Giving it a case can protect the board from unexpected circuit shorts.

  • How do I flash the pre-built image? I am also simultaneously googling around, I hope I find some answers on my own…

Simply decompress the image file (using ‘unxz’) and dd it to an SD card (or download it to the eMMC). You can check the manual for that board.

  • Does it preserve the audio quality from the PS5 or does it alter the audio? I mean, it just acts as a Uac 1 to route audio from one source to another right? No decoding in between? Because I want my dac to handle all the decoding stuff.

Sadly, I do not have professional equipments to measure that, but I am pretty sure that:

  • The input should be the same as connecting a UAC 1.0 card that PS5 accepts. Since the output side is UAC 2.0, there is no reason for the audio quality to deteriorate.
  • I think the data transferred between is purely digital, and it has to be translated from UAC 1.0 to UAC 2.0, so the digital data may be decoded (from UAC 1.0), then re-encoded (to another digital data format to UAC 2.0). I think there is no resampling of the raw audio waveform in between. I am not the audio master for that, but I can not sense any audio degradation from directly connecting it to a 3.5 UAC card (of course, no staticky buzz sound)

I am thinking about building an image that includes the work I mentioned, but that would take some time, and there are two issues I haven’t solved

  1. Set the output volume to max, so you just need to control the volume from your input side.
  2. Handle the audio volume change control. I noticed that from my macOS, changing the volume does not change the output sound directly. It is instructing the UAC device to change its output volume level. Luckily, PS5 is altering the volume sent to the device, so I haven’t solved this issue, yet I can use it on my PS5.
1 Like

Thank you for your reply, once again. Hopefully I will start this project soon and I will keep you updated.