Sample Header Ad - 728x90

Audio playback from assembly language in Unix?

4 votes
1 answer
220 views
# Looking for a simple audio interface for Unix For fun, I'm learning x86 assembly language by porting an old game. The trickiest part is finding a way to play simple sounds (square waves, mostly). The game currently expects to be able to write directly to the speaker. How can I most easily play audio in current Unix systems? ## Criteria To be more precise, this is what I'm looking for (most important criteria first): 1. Can play a waveform. (8-bit, 8000Hz is fine). 1. Simple enough to call from assembly language. 1. Works on a modern Debian GNU/Linux system without needing root for more than simple package installation. 1. Users will not have to install (m)any libraries or other dependencies. 1. Portable across as many UNIX systems as possible. (Particularly {Net,Free,Open}BSD. I expect Solaris, MacOS, and WSL may have their own ways of doing things.) ### Preferences The code I'm porting is 32-bit x86 assembly language and I'd rather not convert it to 64-bit at this time. Also, the code does not need to link with libc and it would be nice to keep it that way, if possible. ____ #### Research Here are some of the avenues I have researched: - /dev/audio This is what I had hoped would work: I'd just open [/dev/audio](https://man.netbsd.org/audio.4) as a file and write bytes to it. Unfortunately, it appears that the Linux kernel no longer comes with that device by default, so folks would have to install a kernel module (snd-pcm-oss) as root. (Also, although this is a lesser issue, Linux uses the old SunOS semantics and does not allow multiplexing). - Direct speaker access (/dev/tty0, /dev/input/by-path/platform-pcspkr-event-spkr) This is what the game was original written to use. However, writing directly to a PC's builtin speaker requires root to configure and a kernel module (pcspkr) under Linux. Also, it does not work on laptops and other machines that don't even have a PC speaker attached. - ALSA Linux does come with a sound system that is available without a kernel module called the Advanced Linux Sound Architecture (ALSA). Other Unix systems can [emulate it](https://ftp.netbsd.org/pub/pkgsrc/current/pkgsrc/audio/alsa-lib/index.html) , although I'm not sure how well. It requires a lot more setup and although it appears it could be controlled directly through ioctl, in general it needs an external library (alsa-lib). The interface is ugly in pure assembly, but can be done in C. On Linux, ALSA is inherently dynamically linked and also uses dlopen to loads up even more libraries (pulse, pipewire) at runtime depending upon the configuration. This is a problem because the assembly code I'm working on is 32-bit, but most 64-bit boxes won't have 32-bit versions of libalsa, pulse, and pipewire installed. - Pipe to a fork/exec'd program A syscall to pipe(2) could be used to create file descriptors so the game can just send raw data to a program, such as sox's [play](https://manpages.debian.org/bookworm/sox/play.1.en.html) command, executed in a fork. While this has the nice property of pushing the problem of portability onto some other program, I'd rather avoid a runtime dependency on an external program.
Asked by hackerb9 (1649 rep)
Oct 23, 2023, 09:59 PM
Last activity: Oct 24, 2023, 12:09 AM