Reading about this takes me back to the late 90s. I had just gotten serious about recording music on my computer and purchased an 866mhz dell pc. I was a using windows 98 and ASIO was still mostly a Steinberg only development and I couldn't afford cubase. I got a hand me down version of cakewalk pro audio 8. I remember the latency of that set up was about 35ms and thinking this is pretty good. There was some degree of having to start playing just slightly early so you could stay on time. With guitar and keys this was doable but I'm sure it would have been maddening with drums. I think it was when fl studio 3 came out that I had the first "daw" that supported ASIO. I remember being blown away at how much tighter everything sounded from that point on.
For those interested in why iOS is better than android, a good summary would just be to say Core Audio was designed from the ground up to be a low level low latency audio API. There are fewer layers in it vs android. When designing OS X Apple knew they had a large professional media market so that got priority. I am interested to see the results of these guys efforts and have wondered when an ASIO equivalent would pop up for android.
With Android the variety of customized android builds on various manufacturers does make this more challenging than it needs to be. As the article points out, many vendors simply break realtime audio by using slow drivers and slow paths.
However, as someone who has dealt with Android, iOS, Windows Phone, and BB audio APIs, Android's audio API really is just amateur hour compared to Apple's, even to the present day. In older versions it was simply unusable for anything more complicated than playing a sound effect or fixed-length mp3 file. Today it functions for more use cases but still abstracts concepts (like codecs and container parsing) in flawed and inconvenient places.
I'm not that familiar with Ubuntu Phone, but from a look at the docs I am concerned that it may have some of the same media issues (or at least the same variations between vendors). According to the architectural overview in the porting guide[1] their Qt-based API sits on top of some abstractions of their own, which then sit on top of stagefright, OMX, and Android's HAL (and thus Android's drivers). Not reassuring.
I'd personally be much more at ease if I saw ALSA sitting directly under Qt, but I can understand why they'd want to leverage the huge Android hardware ecosystem.
Not really. It's the same API they've been using on Macs since the PowerPC days, so they've implemented it for a bunch of different audio chips over the years and that includes a lot of common off-the-shelf solutions. The Hackintosh scene provides fully-capable drivers for all the audio chips you're likely to find in a PC today. Hardware selection or effort put into each driver are almost certainly not factors.
Considering OS X can run on regular old Intel PCs (including the Surface 2!), I'm going to guess that they just have a rock solid, low latency solution, and not something tied to a specific platform.
Thank you, that's exactly what I was wondering. I didn't see anything in the article that gave good reasons for why iOS would be a significant improvement.
Then assembly is more flexible than your favorite high-level language? It's true that you can, by definition, do more with low-level access. And I suppose that's one definition of "flexibility". But I think most developers would use the word to mean that various pieces of functionality can be put together easily. So they might say, for example, that Unix pipes are "flexible". I think I'd usually agree with that meaning.
For example, in assembly we can create a higher level language with an absolutely air-tight, precisely tracing garbage collector that is free of issues like false retention.
We cannot do that in C. That's because there are areas of the program state that are "off limits", and the compiler generates "GC ignorant" code.
What in assembly would allow freedom from false retention is that we know exactly what is in every register and memory location (because we put it there). We know where the GC has to look for root references and where it doesn't have to look.
In C, if we have a pointer p which is the last reference to some object, and is not used any more, and add the line "p = NULL", hoping to drop a reference so the object can be reclaimed, there is no guarantee that the compiler actually generates the code which does the assignment. Since the variable has no next use, and the compiler doesn't know anything about garbage collection, the assignment looks like wasteful, dead code that should be optimized away. Even if the scope finishes executing, the compiler can leave behind a memory location which still references the object.
Here is something else, not related to GC. In assembly language, we can make ourselves a calling convention for variadic functions which know how many arguments they have. As we build up the higher level language, it will have nicely featured variadic functions.
In C, we are stuck with <stdarg.h> which doesn't have a mechanism for the callee to know where the arguments end. The language has no flexibility to add this --- without resorting to approaches which will basically involve assembly language.
In C you can create a higher level language with an absolutely air-tight, precisely tracing garbage collector that is free of issues like false retention.
You can do it portably if you just don't store objects on the C stack, and you can do it non-portably if you do so.
> In C you can create a higher level language with an absolutely air-tight, precisely tracing garbage collector that is free of issues like false retention.
If so, you will be the first; I look forward to the "Show HN:" when it's done.
> You can do it portably if you just don't store objects on the C stack,
Sure, for example, you can do it portably in C if you write a complete emulator for an 80386, and then use that to run an assembly language program. That program isn't a utility for your C code; it's not extending the host C with a garbage collector or whatever else.
If you do not store object references on the stack, your use of C is severely crippled to the point that it's not really C any more. For one thing, C function arguments are on the stack (or, more abstractly, "automatic storage"), so say goodbye to conventional use of C argument passing: the backbone of most normal C programming.
That garbage collector isn't for C. C has automatic storage, and a proper garbage collector has to traverse it.
> and you can do it non-portably if you do so.
Sure, if non-portably means going as far as forking a specific C compiler with your custom hacks, and requiring that C compiler, or else living with the imprecision and taking a whack-a-mole approach to plugging the issues as they arise.
Chicken scheme uses C function calls, and merely requires a contiguous stack for automatic storage (which is technically non-portable, but doesn't require forking a compiler):
You're ignoring the fact that speed is paramount (the whole point of the article). If you want flexibility and speed, you're going to look at using assembler (where you can do anything that can be done, running as fast as it can run) instead of a high-level language (where you have to work with packaged functionality and aggregates hiding complexity). No, it's not going to be easy.
The fact that Apple totally controls both sides of the symbiotic audio hardware & SDK running on a tiny set of products, while Android must have an SDK which accommodates an unknown range of hardware for hundreds of products, means iOS will have an inherent advantage.
Heavily down voted for taking a one line comment about whether more or fewer layers of abstraction is more flexible, and using it to beat your "I hate apple" drum about terms and conditions and control and Muh Freedoms.
You're being that guy, so obsessed with a thing that you see it everywhere and think every conversation is about it.
I am not sure why this is downvoted. Abstraction layers are often added to give flexibility and ease of use, sometimes at the cost of performance. For example ALSA has features like muxing together audio from several apps, while a lower level API might only allow one app to use audio.
I think it's being downvoted because the point of abstraction layers is generally to make specific things easy at the cost of making most other things much harder. For example, Rails makes building web apps easier, but it would be much harder to make a command-line program in Rails. Ruby itself is fine for command-line programs, but there are a host of things that are impossible using it which are doable with raw C. That's why Ruby allows for C extensions: it breaks Ruby's abstractions, but restores some lost flexibility.
In that sense, flexibility and ease of use aren't synonyms; they're opposites. An open flame is flexible but not easy to use, so we have the toaster, which is easy to use but not flexible at all.
iOS can mix audio while preserving low latency. It works much better because CoreAudio is basically a full audio routing and mixing engine and forces more realtime-ish requirements on implementations. The system level engine just takes audio from apps as if they were submixers.
None of that stops you from having a high-level API on top, and in fact iOS has several at different levels of abstraction: AVAudioEngine gives you a lighter weight but object-oriented engine that's less complex to setup. AVAudioPlayer handles almost everything for you.
Just came here to say that. The fact that core audio is a great performing API means even less performance critical stuff still gets the benefits of it even if the easy to use abstractions like AVAudioPlayer give up some flexibility and performance vs the native API. While abstraction can make things more flexible, I would argue that the main purpose is ease of use and hiding implementation details.
In your ALSA example the lower level API doesn't prevent you from mixing audio, it simply isn't as easy because you must implement it yourself, this could be arguably more flexible as well.
Abstractions can hide features of the hardware but they cannot create new hardware. Whatever the abstraction is doing the client software could do instead with the lower level API.
So I would say abstraction layers are often added to give ease of use, sometimes at the cost of performance and flexibility.
For those interested in why iOS is better than android, a good summary would just be to say Core Audio was designed from the ground up to be a low level low latency audio API. There are fewer layers in it vs android. When designing OS X Apple knew they had a large professional media market so that got priority. I am interested to see the results of these guys efforts and have wondered when an ASIO equivalent would pop up for android.