MacIcecast
is an IceCast client for Mac-OS that supports MP3
and AAC
streaming at standard bitrates and sample-rates.
- Boost::ASIO for client-server communication
- LibMP3LAME for MP3 encoding.
- FDK-AAC for AAC encoding.
- AudioToolBox for audio-input.
- Foundation and Core Foundation for data-types.
- MSLogger for thread-safe logging.
Audio streaming software requires high performance and minimal latency to ensure smooth playback without glitches. In C++, virtual functions introduce a level of indirection through the virtual table (vtable), which can add overhead to function calls. While this overhead is typically small, inefficiences can accumulate and even microseconds delays are audibly discernable. To meet strict real-time constraints, MacIcecast
was designed to avoid virtual functions, instead using static polymorphism.
std::variant
enables static polymorphism by allowing a type-safe union of multiple types, chosen at compile time. Instead of using virtual functions, you can define a std::variant
with the types you want to handle and use std::visit
to apply a visitor function to the active type. This eliminates runtime overhead from vtable lookups, as type resolution occurs at compile time. For example, std::variant<TypeA, TypeB, TypeC>
lets you store either TypeA
or TypeB
or TypeC
and perform operations on them without dynamic dispatch, improving performance in scenarios where runtime polymorphism is unnecessary. In the case of MacIcecast
the TypeA
and TypeB
are encoders of specific bitrates, sample-rates, channels, and formats. The supported configurations are
- Formats: MP3, AAC
- Channels: Mono, Stereo
- Bitrates: 64 kbps, 128 kbps, 256 kbps
- Sample Rates: 44100 Hz
This results in 12 permutations. 12 template specialization is a modest price to pay for static polymorphism !
- Extend the
client
library with specializations forIceCast
,ShoutCast
, etc. IfIceCast
andShoutCast
have vastly different packet structures, then this extension would require further template specializations such asMicrophone<Encoder<Client>
.
Managing lifetime of std::variant
instances
Playing a PCM using FFplay
ffplay -f s16be -ar 44100 -ac 2 hahaha.pcm
When creating a new AudioQueueNewInput the callback is a static
method.