Play sound in linux without ALSA

Low-level audio programming in linux seems to be done exclusively using ALSA (asoundlib).
As asoundlib is user-space, at some point it will call into the kernel to play audio.
I understand that asoundlib is very small and in practice there's no real overhead in using it. However, to understand what is really going on I'm trying to bypass asoundlib and talk directly to the kernel to play audio (just a simple buffer like in Handmade Hero)
I can't find any source examples of doing this. Even embedded linux lecture slides I saw scouring youtube for linux audio they used asoundlib. Is it really that difficult to play an audio buffer without a user space program to abstract the linux kernel calls? Am I missing something here?

Edited by Ryan on
asoundlib source code is fully available here: https://github.com/alsa-project/alsa-lib
So you can trace the functions you use from it down to actual syscalls it makes (ioctl).

Basically it means sending and receiving bunch of messages in a special structs using ioctl. I'm not sure if that is documented anywhere - so you will probably need to dive deep in alsa-lib source code or kernel code to understand the interface.

Here's alternative library called TinyALSA that interfaces with kernel using ioctl without help of alsa-lib: https://github.com/tinyalsa/tinyalsa It has smaller amount of source code, so it might be easier to understand.

Here's somebody's project that shows how to use few of alsa's ioctl: https://github.com/takaswie/alsa-ioctl-test It does not seem to actually show how to play PCM samples, but it might be a good starting point understanding the interface.

Edited by Mārtiņš Možeiko on
If calling the operating system directly isn't enough to satisfy your thirst for knowledge, you can also try building your own sound card and call it using an API for controlling hardware pins directly on a Raspberry Pi (fast execution) or Arduino (fast booting). Most programmers can learn it in a month without any previous education in electronics. The hard work is done by logic chips and there are lots of examples online if you don't want to do the electronic math.

A driver for a sound API is just a program that starts automatically like a service and runs in the background, takes calls from different programs and have exclusive access to the sound card where the manufacturer has implemented everything needed to comply with the API's minimum specification. For retro machine projects however, drivers are usually baked into the program statically for full control over the hardware, so you have to be careful about checking the pin numbers before running a new program designed for different hardware.

Retro tone generators
The simplest version to get started (very old games) is just a 555 timer (very good timing without jitter, even in high frequency) with the tone controlled by adjusting resistance with a digital trim-pot via serial-peripheral-interface (SPI), which will play basic melodies with a single square wave. Another digital trim-pot can be used to adjust amplitude of the sound. Capacitors can be used to smooth the square into a curve and create soft fades on the amplitude to sound like an 1980s synth. The good thing is that you just set the value once per tone and let it continue until you set it to another tone, so no real-time thread nor data-intense buffering is needed.

Modern sound-cards
Sound cards for playing recorded sounds use digital-to-analog (DAC) converters to set the level of each speaker. Usually with SPI, which is essentially to clock in one bit at a time into a shift register and then update the value when it's filled. Then just let the program store some sounds, mix them together with 3D and echo effects in a digital signal processor and prevent overflow when clamping to the output range.

A simple way to get differential drive (signal resting around zero energy using AC current) is to connect a capacitor in series with the speaker, which cause a +- flow when the capacitor is charging up and -+ flow when the capacitor is giving power back. An H-bridge would of course be twice as strong and more accurate, but that would risk short-circuiting the computer if you run the wrong program.

Edited by Dawoodoz on
@mmozeiko
Those repositories are very helpful. Thank you

@Dawoodoz
That is definitely something I plan to tackle down the road. Thanks for the advice.

Edited by Ryan on
wow nice, you have lots of knowladge
I emailed the author of alsa-ioctl-test about buffer underun issues with ALSA. They were very kind and actually wrote this gist for playing PCM buffer without lib-alsa