02/09/2017

Dreams of a wireless intercom system (continued: SW)

PoC Software

I decided to try to not entirely roll my own infrastructure, but to implement an already existing VoIP protocol, since this would give me the benefit of not having to build the server-side of the system, as well as being compatible with already existing clients.

There are smartphone clients for the Mumble protocol that we did try out, but the one for iPhone would not work properly (I know nothing about iPhones so I can't really bring more light on the situation), and I myself found my android smartphone wholly unsuitable for the kind of push-to-talk-like use-case that we had.

So while using smartphones did not work out, it gave me a protocol; the mumble protocol is open, and so are many of the clients. Or to be entirely honest, the availability of the mumble protocol, clients, and servers, is pretty much the reason I advocated that it might be worth trying to replace our PMR radio system with smartphones running said clients in the first place. The failure of this trial is perhaps what started glimpses of custom purpose-built hardware to appear in my mind.

So, I started on the software side by trying to implement a mumble client. Starting on the hardware side would have been a bad move, since it would mean having to invest not only time but also money, before I knew if I could a system running even on a regular computer. I had never before used OpenSSL from pure C, only in Perl, where most of it is hidden away. Getting audio I/O running, and running smoothly, with Alsa, proved to be a quite difficult task as well. I have a few sentences of unpublished blog draft from when the software was much younger, which is aptly titled "Death by a thousand small errors", the tone is something like "Do X he thought. It will be fun he thought. Also do Y and Z because why stop at X."

Continuing putting effort into the software paid off though, and while not a full implementation of the mumble protocol, in fact it's fairly minimal, it works pretty well. There is a repository available at https://github.com/tlvb/rabarber.

It should be said that the software went through a few incomplete revisions, both when it comes to whether C or C++ would be the best suited for the task, and what would be a good architecture to implement. Queues of packets that are generated and consumed and have different subtypes and so on is where C++ with templates and inheritance could come to shine, but if entirely honest, I'm more of a C person at heart. I still got my generics by way of preprocessor macros, and while that may have some avert their eyes so as not to become tainted themselves, I am as happy as a pig in mud and claim it has a certain, hm, rustic charm.

I'm also a champion of the notion that bad software design is not the fault of the language but of the programmer, so most of the code rewrites was not due to me waffling on the language choice, but because I was still figuring out a sensible architecture for the thing, something I find is one if not the hardest things to tackle when approaching a new design.

In the end I have gone for a single-threaded non-blocking I/O setup, where the various subsystems (mainly network and audio, which can be further split into read and write operations) communicate through adding and removing nodes to linked lists. I keep memory allocation and deallocation during run-time as low as possible by getting and returning the nodes from and to memory pools and allocate only when the pool dries out. Freeing memory is done at program termination.
Approximate dataflow for capturing audio and sending it to the server.
Approximate dataflow for receiving audio from the server and playing it. It is more complex than capture, since we may recieve audio from multiple speakers at the same time, and we have to keep separate audio buffers for these.
Next up: hardware

No comments:

Post a Comment