📜 ⬆️ ⬇️

Multiplatform audio player in C ++ and OpenAL

It so happened that I used Windows for most of my life and was used to playing audio files using Winamp. It is very convenient to integrate with the command line - launched any audio file and ready. After switching to Linux and OS X (mostly for work, but I use Macs and at home with Windows), there was an urgent need to find an alternative. I tried out a lot of crafty players. Their main problem is the lack of normal integration with the command line and often support only one of the platforms: either Linux or OS X. With console players, the situation is better: mpg123 and mpg321 do almost exactly what you need. That just appeared one big "but." They do not know how to play .ogg and tracker music ( .it , .mod , .xm , .s3m and others), which also accumulated enough and did not want to part with it.

The fact is that during my programming career I had to write a couple of multiplatform audio systems for game engines: for the Linderdaum Engine and for Blippar, and another small one for this booklet. Why not apply the accumulated experience to write the player yourself? Requirements for the player turned out like this:


In fact, the first version that replaced mpg123 was written in 3 days. A version that could play the entire music collection of ~ 12 thousand files required exactly one month. As a back end, it was decided to use OpenAL for audio output (OpenAL Soft on Linux and official support on OS X). For decoding sound formats, libogg, libvorbis, minimp3, libmodplug and id3v2lib are used. Writing a player “slightly” is different from writing an audio system for a game (except that only one single sound source is needed without any 3D positioning and effects). In fact, the main difference is that sound formats in the wild are not at all the same as sound assets for a game project. There may be broken files, strange tags, non-standard additions at the end of the file, unusual .mp3 in which the sampling rate changes from frame to frame, there may be containers .wav that have a .mp3 stream inside.

The player was conceived as a modular ability to quickly expand to play other formats and to use different back-end. At the core of the entire audio source interface, the iAudioSource abstract class, and the iAudioSubsystem audio system interface .
')
class iAudioSource { public: iAudioSource() : m_Looping( false ) {} virtual void BindDataProvider( const std::shared_ptr<iWaveDataProvider>& Provider ) = 0; virtual void Play() = 0; virtual void Stop() = 0; virtual bool IsPlaying() const = 0; virtual bool IsLooping() const { return m_Looping; } virtual void SetLooping( bool Looping ) { m_Looping = Looping; } private: bool m_Looping; }; 

 class iAudioSubsystem { public: virtual ~iAudioSubsystem() {}; virtual void Start() = 0; virtual void Stop() = 0; virtual std::shared_ptr<iAudioSource> CreateAudioSource() = 0; virtual void SetListenerGain( float Gain ) = 0; }; 

The only implementations of these interfaces use OpenAL for audio output, since support for this API on all three platforms is quite decent.

To decode various formats in PCM we create an iWaveDataProvider interface.

 class iWaveDataProvider { public: virtual ~iWaveDataProvider() {}; virtual const sWaveDataFormat& GetWaveDataFormat() const = 0; virtual const uint8_t* GetWaveData() const = 0; virtual size_t GetWaveDataSize() const = 0; virtual bool IsStreaming() const { return false; } virtual bool IsEndOfStream() const { return false; } virtual void Seek( float Seconds ) {} virtual size_t StreamWaveData( size_t Size ) { return 0; } }; 

And for convenience, just such a factory:

 std::shared_ptr<iWaveDataProvider> CreateWaveDataProvider( const char* FileName, const std::shared_ptr<clBlob>& Data ); 

Various implementations of iWaveDataProvider use third-party libraries to decode audio formats. It turned out very compact and suitable for further expansion of functionality.

The source project is available here: github.com/corporateshark/PortAMP

Maybe one day I will add support for FLAC, but so far there is absolutely no incentive - there is no such format in the home collection of files.

FLAC support now too.

Source: https://habr.com/ru/post/266127/


All Articles