Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

The answer is “not applicable” to all of these. The word clock is unit less, just ticking up each sample. It’s not actually a clock in the normal sense, there is no leap years or anything in it. It’s used to synchronize devices.

Granted, the documentation isn’t the best at explaining it. But if you know what a word clock is in terms of audio, you know what the value is; a counter.



> The word clock is unit less, just ticking up each sample.

That should be in the documentation. Each sample is guaranteed to have an increment compared to a previous sample.

But, it doesn't answer all of the questions.

Does the world clock always start from 0? Is that an assumption that can be made?

Or is the valid range anywhere inside a uint64?

What happens if the number of samples exceeds the length of the world clock unit? Is it allowed to overflow? In which case it violates the assumption that it always just increments.


Even if it counts in picoseconds it’ll take several centuries to roll-over, so these probably aren’t questions you ever need to ask. Though that’s kind of the point: the API and its documentation should highlight the stuff you need to worry about, such as where you get these values from and what they do, and hide everything else that you don’t (internal implementation details).

But that particular API does the opposite. Just typedef-ing that data as an opaque `WordClockTime_t` would go a long way to fixing this, telling API users to ignore how it works internally and enabling automated documentation tools to to locate and list every other API that produces/consumes this particular value. A simple automation-friendly abstraction that would reduce—if not eliminate—the need for additional manually-written documentation. i.e. Put the knowledge in the code and the automation can graph it.

Alas, there’s something about C programming that seems to bring out the worst abstractions in many C programmers… and if they’re being lazy in their API design, they’ll be twice as lazy when it comes to manually documenting it.

--

"What is wrong with giving tree, here?"

"Well, he don't know talking good like me and you, so his vocabulistics is limited to 'I' and 'am' and 'Groot.' Exclusively, in that order."


> Even if it counts in picoseconds it’ll take several centuries to roll-over, so these probably aren’t questions you ever need to ask.

That's an assumption, that an edge case won't happen. Docs exist to spell out where the edge cases are.

Cisco thought a 32bit number for RTP timestamp would never rollover. It happened. [0] Centuries it might take if it's initialised from zero, but it doesn't have to be. And if you don't give the documentation, then you can't expect reasonable defaults to be used.

It's important to know when something like that happens, so that they can also know how to handle behaviour that may well be completely unexpected. Hiding the type doesn't help. It just tells you you're even more on your own if you want to handle exceptional events, which leads to code with holes so big you can drive a CVE through it.

[0] https://quickview.cloudapps.cisco.com/quickview/bug/CSCvc865...


Aye, I’m well aware what can go wrong when an integer overflow occurs. My point was the way Apple presumably[1] uses this particular Uint64 precludes such an event ever occurring within macOS’s lifetime, therefore there’s no need to explain it. If a macOS API generates that value and a macOS API modifies it and a macOS API consumes it, and users should only ever pass it around as-is and never screw with it directly, it’s opaque data and its internal workings are none of their business.

Okay, it would really help if C’s so-called “typesystem” would actually enforce a custom-defined type like `WordClockTime_t` so that client code can’t do stupid/malicious things with it like stick its own arbitrary integers in it; but hey, C. While a sensible runtime would also chuck an exception if a fixed-width integer overflows, rendering rollover dangers moot; but again, C. It is what it is; and so it goes.

But if, as an API designer, you’re going to document every single way your API may potentially blow up during normal/abnormal use then perhaps you should write that documentation in the form of defensive code that validates your API’s inputs and handles bad inputs accordingly. e.g. A timestamp API should not be making its users fret about (never mind cope with) C integer overflows; guarding against any edge-case crap is the API’s job, not its users’.

Again, the problem is not a lack of documentation so much as lack of clarity. A good abstraction shows only what its users need to know and hides everything that they don’t; the more that can be left unsaid, the better. (If an API can’t be documented clearly and concisely, that’s a huge red flag that the API design is bad so needs reworked until it can.) The problem with an API like this is the not-knowing, which indicates deeper, more systemic, failings than merely “needs more documentation”.

..

TL;DR: If your API is puking on its users then don’t start documenting the color and odor of that puke; fix its code so it doesn’t puke again.

--

[1] I say “presumably” because damned if I’m going to spend hours spelunking Apple’s crappy documentation just to find out exactly where this mWordClockTime value comes from and where it goes to.


> If a macOS API generates that value and a macOS API modifies it and a macOS API consumes it, and users should only ever pass it around as-is and never screw with it directly, it’s opaque data and its internal workings are none of their business.

But that's not the case. You get to set mWordClockTime as part of the init [0]. If you can initialise a value, but aren't given bounds for the value, then the documentation has screwed up.

The value is something the developer can create, and pass in when creating any AudioTimeStamp, which you will be doing a lot of if you're dealing with sound.

This isn't an arbitrary value you can just rely on to be correct, there may be good reasons for altering the value, such as when splitting sound into several thousand chunks and rearranging them.

It's a part of the exposed API - it needs to be documented how it behaves.

For a different take on a similar problem, let's look at how PulseAudio handles it [1].

> pa_core doesn't have any interesting functions associated with it, it is just a central collection of all the components and globally relevant variables. You're not supposed to modify the fields, at least not directly.

This is how you abstract away an API safely. The dev knows up front that pa_core is the type that'll be used, and that other functions will be modifying the sample cache for them - that is, they can't supply a value directly to the type or they've entered unsafe behaviour.

They can go off and find the right setter.

What follows on that page is only a courtesy, and can clearly not be used safely in most programs. It doesn't need to be there at all.

So the dev finds [2], where they call the client to get the sample.

And whilst duration is a uint64, is also has a few more things in the docs, such as the value can be lazy, so you need to check it exists before using it, and the property can raise an error when you try to access it and it doesn't yet exist. You'll also find that this a property (so you won't be creating it), generated by an interface, and where to find that interface.

I mean, I'm not one to compliment PulseAudio's documentation. It is an awful mess, just like the internals.

But they've given us a lot more than Apple bothered to.

[0] https://developer.apple.com/documentation/coreaudiotypes/aud...

[1] https://www.freedesktop.org/wiki/Software/PulseAudio/Documen...

[2] https://www.freedesktop.org/wiki/Software/PulseAudio/Documen...


“You get to set mWordClockTime as part of the init”

While I’ve never had the pleasure of dealing with Core Audio, I’m getting the strongest impression that our problem is not that its API documentation is inadequate, but that its API was designed by a bunch of absolute hacks and bums.

In which case, asking for additional documentation is like asking for additional band-aids after severing your leg with an exploding chainsaw. Never mind for a moment the current bleeding; fundamentally you’re tackling the wrong problem. The right approach is first to make absolutely sure exploding chainsaws never get sold in the first place. Once that’s addressed, then worry about providing non-exploding chainsaws with adequate training and safety gear.

If the user has to initialize the struct directly then yes, the docs absolutely should state what values to use. However, unless there is some absolutely overriding reason for doing this then really, no, the right answer is to do what the old Carbon C APIs and Core Foundation do, which is to provide a constructor function that correctly populates it for them, and then document that. The documentation is shorter and simpler, and there is less to go wrong. Plus users do not need to write their own guard code—a massively pointless duplication of effort.

For instance, the LSLaunchURLSpec struct (https://developer.apple.com/documentation/coreservices/lslau...) is a good example of a manually-populated struct with appropriate documentation.

But in most cases, when working working Carbon/CF you don’t need to know any of these details because the structs are initialized and disposed for you, and these functions all follow standardized naming conventions so are trivial to locate as well. This is Abstract Data Types 101, and shame on the CA PMs for thinking they’re special snowflakes and simply dumping all their shit onto their users instead, and shame on the dev managers above them for letting them do so.

..

Incidentally, this is why I always fight anyone who says developers are too busy/special/autistic/etc to documentat their own APIs. Yes, producing high-quality public documentation needs specialist technical writers and editors on top of (but not instead of) its original developers, but there is no better first test of the quality of your API design like being forced to explain it yourself. I know this; I’ve thrown out and replaced more than one working API design over the years simply because I found it too difficult or confusing to explain.

--

TL;DR: Don’t document Bad APIs. First make them into good APIs, then document that.


There is a glossary in the CoreAudio docs, but it hasn't been updated since 2010. And it doesn't include an entry for WordClock.

You could argue that generally the docs are good enough to Get Shit Done. And people are Getting Shit Done on the platform as a whole. So there's no problem.

But it's a shame Apple doesn't consider better docs a priority. IMO it's not a good look for a trillion dollar company.

More, I don't know if insiders use the same doc base. If so it's definitely wasteful, because newcomers are going to be wasting time and effort trying to get up to speed.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: