You
can do cat file.au >/dev/audio on a lot of Unix-y OS's. For wav, the problems you mention are solved with "sox" which converts the wav file to raw data with suitable options.
All of the problems you mention are problems of the interfaces exposed by the files, not problems with the "everything as a file" idea in itself.
Look at /proc on linux. /proc/[pid] represents a running process, but it's a directory, not a file, all the information about that process are inside.
A hypothetical filesystem API for audio designed to be friendly might expose a /proc/sound/[device]/name file containing a user friendly description and a /proc/sound/[device]/output file that a converter gets mounted at that you can just copy files to, and a /proc/sound/[device]/control that accepts commands like "pause" or "play".
You also seem to also be assuming that these interfaces are meant for ordinary end-users. While some of the functionality does make it easier for end-users to interact directly with the lower levels of the system, nothing precludes friendlier interfaces being put on top of it.
What it gives you is an interface that has a bunch of standard tools you can use to operate on them, either because they're simple enough to use directly, or to make building the user friendly interfaces more easily, and that which is at the same time reasonably explorable if it's well designed. /proc is a good example of this - you can poke around in it and learn a lot about your system with just a standard shell without having the faintest idea about how it's structured initially. Meanwhile, the non-file-related system calls require you to write code to test them out - they're far more opaque.
> But this approach doesn't actually work for monitoring growing files; the select() will just return immediately with read-ready even if you're at EOF.
This really shouldn't be surprising. select() specifically tells you if the filedescriptor is read for read. A filedescriptor is ready to read from if there is more data or you're at the end of the stream. The behavior is entirely consistent. Perhaps a way of requesting notification only if there is more data to read, rather than if there's more data or end of the stream, would be useful, but that is not what select() provides. It illustrates some of the flaws in the Unix system calls, not an inherent problem with a filesystem interface.