This doc is pretty old, but still was invaluable for actually writing a sound card driver when I was tasked to do so. Frankly, ALSA is one of the most over convoluted interfaces I've ever had the displeasure to work with when writing one.
Unfortunately, I wasn't writing a PCI driver -- I was writing an I2C/I2S driver that used the ASoC subsystem and its insane DAPM and audio routing. Most of ALSA seems to have been abandoned by its creators, and conventions are not adhered to in 99% of the routing and DAPM graphs. Since they're all stringly typed and the userland vs. the kernel naming is completely disjoint, this means that its practically a black art to get those graphs right.
Add pulseaudio's complete insanity with regard to hardware parameters and audio routing, and you have one of the most toxic development experiences of my life.
Frankly, I'm amazed anybody can get anything done with this system at all, and I'm amazed Linus hasn't ripped it all out by now. This is the one subsystem that should have been the easiest to implement and get right.
Audio on Linux is such a total shitshow that Android replaced ALSA with a total workaround called "tinyalsa" and ChromeOS replaced pulse and half of ALSA's routing behaviors with cras.
Finally, ALSA doesn't have any routing behavior. You seem to be stuck thinking about a tiny subset of audio interface hardware (admittedly, perhaps the biggest selling because it's builtin to most mobos and SoCs). The pro-audio/music-creation/pro-sumer end of the audio interface world features hardware that doesn't work like the garbage that Intel's HDA model forced into the world, and ALSA was created without a focus on HDA (because it didn't even exist at the time ALSA was being shaped). The "pin routing" model that HDA uses is not shared by a single high-end audio interface, is frequently violated by manufacturers and does almost nothing but cause headaches for system programmers and architects.
Audio on Linux is actually better at a technical level than on other OS's, but the user experience is frequently poor. That's a very different story, and one that doesn't really lie at ALSA's feet at all.
> Audio on Linux is actually better at a technical level than on other OS's, but the user experience is frequently poor. That's a very different story, and one that doesn't really lie at ALSA's feet at all.
Well, if it wasn't for the lack of a driver for my sound card (ESI audio), I would use linux for my DAW. Jackd alone with the proper configuration software is a godsend.
I definitely prefer ALSA to whatever windows tries to do with sound when working with sound card radio systems. I've had way too many problems with windows just arbitrarily rerouting things and switching input/output devices with no user input.
(I would LOVE to write an ALSA driver for a different transport mechanism, but I'm not even remotely clear on how the different parts of ALSA relate, and this is after months of studying https://dri.freedesktop.org/docs/drm/sound/kernel-api/alsa-d... and I can't seem to make head nor tails of the different layers, partial layers, etc.
I am sufficiently familiar with callback-api's and running audio codec's on the bare metal and via microcontrollers.)
Additionally, how does Device Tree and Device Tree Overlays fit into this picture?
Are ALSA transports limited to PCI, USB, etc?
I haven't found a single ALSA driver tutorial online from the last decade.
I've had a plethora of OTHER nonsense, such as why a given soundcards multichannel support only functions as "Surround Sound 5.1", replete with high-pass-filters on the primary pair of outputs it thinks are "Front L & R"...
In terms of ALSA configuration, there appear to be a zillion ways (distro specific) to do so, and none of them appear actively used on my boring old Ubuntu 16.04 system, and I'm not even sure where this mystical blackbox asound.conf stuff is actually occuring these days, but suffice it to say that there are no userland applications that actually appear to address the audio interface properly, and there appear to be WAYYYYY too many abstraction layers hiding crucial hw configuration details from the people who need to use it: aka every computer audio person ever.
I guess what is missing for me is this info on what part of ALSA one needs to write when trying to bring-up new hardware, how DMA can be used, in case of trying to directly interface a la ASoC, or how externally controlled audio devices (an MCU running the codec I2S interfaces, for examples) could be used to load a buffer up and present it to the computer (as the buffer interrupt rate will be closer to 1-2khz even with a 32 frame buffer, vs the strict requirements of the codec themselves)
It almost seems as if that info is not online, or that my search terminology is incorrect
I wrote several ALSA drivers in the early 2000's. It hasn't changed much since then, but I'm not close enough to ALSA anymore at the kernel level ot offer any advice. What I can tell you is that stuff like "Device Tree" and "Device Tree overlays" are concepts restricted to one specific class of audio interface (based on HDA and its concepts), and do not exist in any of the devices you would actually buy to function as an audio interface.
There are no "new" ALSA driver tutorials because, IIUC, ALSA hasn't really changed much in the last decade. Just like CoreAudio and the older Windows APIs (they finally have some new ones worthy of the name "audio API").
Your complaint about "why a given soundcards multichannel support only ..." is really just a reflection of the screwed up nature of HDA and its cousins. Again, if you go and actually buy a "real" multichannel soundcard, you won't run into this issue. If you're stuck with what a mobo or SoC maker gave you, then the problem is typically with the fact that they changed the h/w setup and relied on a BIOS hack to make it work.
Driver stuff is "broken" with respect to much newer device hardware, but that's hardly suprising when Android ripped out ALSA and so nobody working on mainline kernels has much motivation to make ALSA work with the sort of audio hardware that shows up in things like phones.
I do know that on very contemporary RPi systems, things like Ardour and JACK (both of which I wrote, by the way) work out of the box.
There are two primary audio "transports" as you call them today: USB, which is more or less fully and totally supported by the class compliant ALSA driver (thanks, iPads, for enforcing a "no driver" policy") and HDA-via-PCI which is technically supported but the specs allow so much wiggle room that hardware makers (not audio hardware, mobos and SoC stuff) regularly and routinely break things.
Most of your complaints seem to be centered on the HDA-via-PCI family of devices, and there's really not a lot Linux can do there. MS provides BIOS patches, Apple builds their own hardware - what's Linux supposed to do with a useless standard that is routinely ignored?
I appreciate that "i just want my laptop audio to work" is a legitimate issue (although for the most part, they just do). But that's a tiny corner of what ALSA and audio is all about, and we're badly hurt by the (non)standard HDA and all of its misfeatures (which, as I noted Apple and MS workaroudn in different ways).
Oh, I'm specifically referring to pro-audio (a Tascam 8x8 I/O, and a Presonus 1804) interfaces, that my Ubuntu 16.04 system was pretending were "surround sound" interfaces, so it's something configuration related, not ALSA/driver itself.
(I'm exclusively interested in pro-audio, vs whatever the OP of this comment was concerned with)
I have 2 interests with regard to this:
1) writing a driver for a home-brew soundcard with an MCU running the DAC/ADC TDM interfaces, and interfacing with the computer via SPI, as it's clock is a function of the audio sample clock running the whole shebang, and I never saw an SPI transport for ALSA in my life
2) just generally trying to get to the bottom of how linux/ALSA sees my soundcard hardware (the specific multi-channel audio interface being interpreted/configured as a surround sound interface etc.)
I mentioned the Device Tree Overlays as it appears that this is how the Bela system manages it's PRU supported audio codecs in Alsa mode, but consider it a clueless comment off-topic...
Thanks for writing back, I appreciate it!
I'm a big Ardour fan.
Jack is standard for everything in pro-audio these days, and yes, I know that you literally have spent 30 ++ years in this realm, hence my questions...
By the way, when they ask for "quantizing audio" in Ardour, it's already there! I can say that the following works GREAT in Ardour:
1) strip silence function
2) snap the audio bits created by #1 to grid/quantize value.
I guess I'm not entirely clear on what I would need to implement to use ALSA's PCM interface with an arbitrary transport, given a defined memory area and buffer size.
I appear to be fuzzy on the topic of what parts I need to write and what is already provided, generally.
The class-compliant USB interfaces do indeed generally "just work"
(with the configuration issues I mentioned on my particular system, but I'm not clear on where this occurs, "channel mapping" or somesuch calling my 8 outputs a singular surround interface etc...)
so, that workgroup has an admirable goal, and such a guide is what I do crave, and I confess to being basically ignorant and having difficulty in comprehending all the folders full of linux and legacy STUFF in alsa ... where are the drivers? what even is the driver? lol.
what interfaces must a driver implement?
what parts of ALSA are required when opening, configuring, and streaming to/from a device and what parts are ALSA itself and what are in the particular driver? (not at all helped by having arch's on the top folder level, right next to transports/busses)
and core having been called the heart of ALSA but yet all I see there is oss ioctl and something about a sequencer!? huh? sequencer? )
Opening a device, configuring it, registering a callback function, this is all standard across API's and people are used to PortAudio, SDL, etc.
I've hooked up audio converters to microcontrollers, fpga's etc and am familiar with the hw signals entailed for interfacing over I2S, TDM over I2S, control interfaces via SPI and I2C, the timing of these signals, and the particularity of crystals such as the venerable 11.2896mhz, and I would go so far as to swap out a different crystal and force a singular sample rate on the entire system forever, yes I'm a fanatic, lol... but I digress... I have no notion of what the host side of an audio interface looks like, and have never seen the "other side" of the mcu/fpga in your blackbox usb soundcard. (xmos? some glorified ftdi chip?)
Am I to understand that ALSA only knows about the precise sample-clock-timing at each full audio buffer interrupt or period?!
What does the host side of an audio interface look like? (some pcm_stream's? any control interfaces? is the sample clock not passed onward to the host from the device (mcu+codecs)?)
I guess what I'm fundamentally puzzled about is how all these folders of ALSA "stuff" inter-relate and how the heck the sprawling collection of related modules actually relate to each other, and what one must actually do in order to bring up new hardware under ALSA...
any advice, psychiatric or audio hardware related, taken to heart.
I don't have the time and these days don't really have the expertise to take you on a tour of the ALSA codebase.
All audio interfaces that I'm familiar with work on basically the same principles (except for a couple that I think should be thrown on the junk pile for design reasons). They have a memory buffer which they treat as a ringbuffer, and periodically as they traverse the ringbuffer they raise an IRQ with the CPU. The CPU reads/writes from/to the buffer, and assuming that it does so on time, things continue on smoothly. These days most devices can function as DMA bus masters, meaning that the CPU does not need to explicitly move data to/from the device - the device is given an address in system memory and uses that.
Very few devices have a register that can be read to determine the read/write pointer position within the buffer. Therefore a design predicated on this idea (which you'd think would be a no brainer) is going to fail for the majority of devices.
So the "pcm" zone of an ALSA driver is the part that takes care of handling interrupts and data transfer. ALSA represents each direction as a separate device, a decision I was never in love with, but CoreAudio and most Windows driver APIs do the same so what can you do ...
Then there's an entirely separate aspect to many audio interfaces which is far more complex and difficult. In ALSA it is represented by the "control" API, in which ALSA tries to present as many of the controls present in the device and allow them to be manipulated. Since there is a massive variation in the number, nature and interdependence of these controls, this is very challenging to present to the user. This is partly why there are often dedicated control applications for high end cards on Windows and macOS.
There's no particular connection between the PCM and the control aspects of an ALSA driver, although obviously they are related and implemented together.
Sample clock is not visible to the CPU. Sample clock exists only at the device hardware level. Deciding which clock source to use is an option on a few pro-level cards, and ALSA "exports" this functionality via the control API.
USB audio device support is particularly problematic because the USB bus is uniquely unsuited to this purpose, and also because despite the standard, many/most devices have "quirks" that need to be accomodated in order to function fully. As a result, although there is really just a single driver per USB class, there is quite a bit of code associated with dealing with quirks of specific devices. This is decreasing for reasons I alluded to early: if you want to sell a device to iPad users, you cannot tell them to install a driver, and so manufacturers have been getting steadily more and more conformant.
> Audio on Linux is such a total shitshow that Android replaced ALSA with a total workaround called "tinyalsa" and ChromeOS replaced pulse and half of ALSA's routing behaviors with cras.
Cras is great. When I run into problems with it I know that they aren't due to mis-configuration of an ugly, overengineered API but instead due to a bug in a sexy, streamlined replacement for it.
CRAS doesn't "replace" ALSA's routing behavior: ALSA doesn't have any of the kinds of routing behavior that CRAS embodies? Why not? Because ALSA is a kernel driver stack and CRAS is a userspace audio server designed explicitly to provide functionality on top of ALSA. From the CRAS docs:
"Put an audio server in between Chromium and ALSA that can change how audio flows on the fly. "
You might think ALSA is "overengineered" but that's probably because you have no familiarity with the hardware or workflow that it is engineered for.
There's no reason why that (using a class compliant MIDI USB device) would not just work out of the box. I have more than a dozen MIDI/USB devices in front of me, and they all work on a plug-n-play basis with my Linux systems. Some of them actually a little better on Linux than on macOS.
I was trying to get tracktion waveform 8 to see a behringer crave synthesizer. It has a built in sequencer so wanted to record the notes programmed on the behringer
Unfortunately, I wasn't writing a PCI driver -- I was writing an I2C/I2S driver that used the ASoC subsystem and its insane DAPM and audio routing. Most of ALSA seems to have been abandoned by its creators, and conventions are not adhered to in 99% of the routing and DAPM graphs. Since they're all stringly typed and the userland vs. the kernel naming is completely disjoint, this means that its practically a black art to get those graphs right.
Add pulseaudio's complete insanity with regard to hardware parameters and audio routing, and you have one of the most toxic development experiences of my life.
Frankly, I'm amazed anybody can get anything done with this system at all, and I'm amazed Linus hasn't ripped it all out by now. This is the one subsystem that should have been the easiest to implement and get right.
Audio on Linux is such a total shitshow that Android replaced ALSA with a total workaround called "tinyalsa" and ChromeOS replaced pulse and half of ALSA's routing behaviors with cras.