# Audio A program that wants to make a sound opens `/dev/dsp`, writes PCM to it, and closes it. That is what UNIX audio has always been, and it is what this is. ```sh tone 440 2 # 440 Hz for two seconds ``` Three pieces, in the order a sample passes through them: | | | | --- | --- | | **`/dev/dsp`** | `kernel/dev/audio.c`. A character device: `write()` is audio, and a handful of OSS ioctls say what the samples are. | | **AudioEngine** | The same file. Everything above a driver that is not specific to a chip: the format, whether there is room, and what a write does when there is not. | | **a driver** | `kernel/drivers/audio/ac97.c` today. Bound by class, exactly as a display driver is — `device_find_class(DEVCLASS_AUDIO)`. | ## Why OSS and not something new The ioctls are `SNDCTL_DSP_SPEED`, `SNDCTL_DSP_CHANNELS`, `SNDCTL_DSP_SETFMT`, `SNDCTL_DSP_SYNC` and `SNDCTL_DSP_GETOSPACE`, with OSS's own numbering. They are not invented here and they are not copied for nostalgia: every UNIX audio program that has ever been written knows them, and the only thing a different set would achieve is making ports harder. They are **read/write** ioctls, which is the part that matters. A program asks for 44100; the device sets 48000 and writes 48000 back; the program resamples. One that ignores the answer plays everything 9% fast, and that is its bug rather than the driver's. `configure` in the class works the same way, and for the same reason — a driver that can only do 48 kHz says so *there*, rather than by quietly failing a `write()` later. ## What the engine is, and what it deliberately is not It owns format negotiation, the "is there room" question, and blocking. Those are genuinely shared: a second driver should not have to re-implement *wait until the speaker has caught up*. **It is one stream.** Mixing several programs into one device is a real feature with a real design behind it, and building it before anything had played a single sound would be exactly the mistake [../plan/1.0.md](../plan/1.0.md) keeps a register for: work that exists and is connected to nothing. The second program that wants to play at the same time is what should cause it to be written. ### Waiting on the tick, not on the device `audio_wait()` sleeps until the next timer tick rather than on an interrupt from the sound card, which looks like the lazy choice and is not. A ring that drains is a ring with room in it, so asking again in ten milliseconds always makes progress. Sleeping on the *device* would make audio depend on the interrupt arriving — and on a machine whose line is misrouted, or a chip that needs a kick, that is not a stutter, it is a writer that never wakes up. The interrupt handler is still there and still accounts for finished buffers; the point is that deleting it would cost efficiency and not correctness. ## AC'97 first, and HDA later AC'97 is the simplest audio device that exists both on real machines and in QEMU. Intel HDA is what a laptop built this century actually has, and it is a much larger driver — codec enumeration, CORB/RIRB, stream descriptors. Writing it first would have meant writing two unproven things at once: a driver, and the interface it is the only user of. The class is the whole point of the order. HDA arrives as a second `struct audio_ops` and nothing above it changes. ### How it plays The chip reads a *buffer descriptor list*: 32 entries, each naming a physical address and a length. It plays the entry at `CIV` and stops when it reaches `LVI`, the last valid index. Playing continuously is therefore not "start it and walk away" — it is keeping `LVI` ahead of `CIV`, which is what `queue()` does, one 4 KB descriptor at a time. Retiring finished descriptors happens in **both** `queue()` and the interrupt handler, through the same `tail` pointer so the two cannot disagree. That is the same "the interrupt is an optimisation" stance as above. Both register files are **I/O ports**, not MMIO — which is why nothing in the driver maps anything. `bar[n].is_io` is what says so, and a driver that `ioremap`ed these would be mapping a port number as though it were an address. ## How it is tested QEMU's `wav` audio backend writes what the guest plays to a file, so the test is not "it did not crash": ```sh make qemu # QEMU_AUDIO puts an AC97 on every target tone 440 2 ``` and the file is measured — 1.97 seconds of 44.1 kHz stereo, peak amplitude 14177 against the tone generator's table maximum of 14178, and 880 zero crossings per second, which is 440 Hz exactly. `wav` rather than a host backend on purpose: a build machine may have no sound card, no PulseAudio and no session bus, and it is the only backend whose output can be *checked*. To actually hear it: ```sh make qemu QEMU_AUDIO='-audiodev pa,id=snd0 -device AC97,audiodev=snd0' ``` ## What it does not do - **Recording.** `read()` on `/dev/dsp` returns `ENOSYS` rather than zero, because zero is end-of-file and a recorder would write an empty file and call it a success. - **Mixing.** One stream; see above. - **Mono.** The driver reports two channels because AC'97 plays stereo, and a mono stream would have to be doubled somewhere. The write-back tells the caller, which is the whole reason the ioctl has a direction. - **Formats other than signed 16-bit little-endian.** It is what every PC audio chip takes natively and what a WAV file already contains. Converting in the kernel to satisfy a caller that could have converted first is not an obvious trade. - **Volume.** The mixer is set to full and left there. How loud a machine is is not the kernel's decision, and a device that comes up silent reads as broken to whoever is testing it.