miniaudio: A C/C++ cross-platform, single file, public domain audio library

For a while now I've been working on a little audio library that I thought some of your guys might be curious about. It's a public domain, single-file C/C++ library with a focus on simplicity. It's primary purpose is to simply connect to a device and handle the data transmission with appropriate data conversions. It is not a 3D audio API.

I've called it miniaudio, and you can find it on GitHub: https://github.com/dr-soft/miniaudio. From the readme:

Features
  • A simple build system.
    • It should Just Work out of the box, without the need to download and install any dependencies.

  • A simple API.
  • Supports playback, capture and full-duplex.
  • Data conversion.
    • Sample format conversion, with optional dithering.
    • Sample rate conversion.
    • Channel mapping and channel conversion (stereo to 5.1, etc.)

  • MP3, Vorbis, FLAC and WAV decoding.
    • This depends on external single file libraries which can be found in the "extras" folder.



Supported Platforms
  • Windows (XP+), UWP
  • macOS, iOS
  • Linux
  • BSD
  • Android
  • Raspberry Pi
  • Emscripten / HTML5


Backends
  • WASAPI
  • DirectSound
  • WinMM
  • Core Audio (Apple)
  • ALSA
  • PulseAudio
  • JACK
  • sndio (OpenBSD)
  • audio(4) (NetBSD and OpenBSD)
  • OSS (FreeBSD)
  • AAudio (Android 8+)
  • OpenSL|ES (Android only)
  • WebAudio (Emscripten)
  • Null (Silence)


Building
Do the following in one source file:
1
2
#define MINIAUDIO_IMPLEMENTATION
#include "miniaudio.h"

Then just compile. There's no need to install any dependencies. On Windows and macOS there's no need to link to anything. On Linux and BSD, just link to -lpthread, -lm and -ldl.

Simple Playback Example
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#define DR_FLAC_IMPLEMENTATION
#include "../extras/dr_flac.h"  // Enables FLAC decoding.
#define DR_MP3_IMPLEMENTATION
#include "../extras/dr_mp3.h"   // Enables MP3 decoding.
#define DR_WAV_IMPLEMENTATION
#include "../extras/dr_wav.h"   // Enables WAV decoding.

#define MINIAUDIO_IMPLEMENTATION
#include "../miniaudio.h"

#include <stdio.h>

void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount)
{
    ma_decoder* pDecoder = (ma_decoder*)pDevice->pUserData;
    if (pDecoder == NULL) {
        return;
    }

    ma_decoder_read_pcm_frames(pDecoder, pOutput, frameCount);

    (void)pInput;
}

int main(int argc, char** argv)
{
    if (argc < 2) {
        printf("No input file.\n");
        return -1;
    }

    ma_decoder decoder;
    ma_result result = ma_decoder_init_file(argv[1], NULL, &decoder);
    if (result != MA_SUCCESS) {
        return -2;
    }

    ma_device_config config = ma_device_config_init(ma_device_type_playback);
    config.playback.format   = decoder.outputFormat;
    config.playback.channels = decoder.outputChannels;
    config.sampleRate        = decoder.outputSampleRate;
    config.dataCallback      = data_callback;
    config.pUserData         = &decoder;

    ma_device device;
    if (ma_device_init(NULL, &config, &device) != MA_SUCCESS) {
        printf("Failed to open playback device.\n");
        ma_decoder_uninit(&decoder);
        return -3;
    }

    if (ma_device_start(&device) != MA_SUCCESS) {
        printf("Failed to start playback device.\n");
        ma_device_uninit(&device);
        ma_decoder_uninit(&decoder);
        return -4;
    }

    printf("Press Enter to quit...");
    getchar();

    ma_device_uninit(&device);
    ma_decoder_uninit(&decoder);

    return 0;
}

Edited by David Reid on
This looks great!

I'm now using it in one of my projects instead of SDL (which was only being used for audio).
It was very simple to set up, and I haven't found any issues.

Thanks for putting it together.
Looks great, indeed.

I managed to create a working port of your "Simple Playback Example" in Odin, by binding to a compiled version of the library. I'm looking forward to see how far I can go with this!
Thanks!

vassvik
I managed to create a working port of your "Simple Playback Example" in Odin, by binding to a compiled version of the library. I'm looking forward to see how far I can go with this!


I just pushed a new version with API changes, just so you're aware :)
In case anybody was interested, I've just done an update to mini_al. Some additions since my original post:

  • Added support for macOS and iOS via Core Audio.
  • Added support for Emscripten via SDL.
  • Added PulseAudio and JACK backends. PulseAudio is now the default on Linux.
  • Added a decoder abstraction with support for WAV, FLAC, MP3 and Vorbis. This depends on other single file public domain libraries, copies of which are in the mini_al repository.
  • Further simplified the build system by removing the dependency on ALSA development packages for Linux, and WASAPI and DirectSound headers for Windows. mini_al should compile clean out of the box on Windows, macOS and Linux without the need to install any external dependencies.
  • Lots of improvements to format, channel and sample rate conversion.
  • Added support for dithering to format conversion.
  • Lots of bug fixes and optimizations.
  • Lots of breaking API changes. Sorry!
  • Probably a lot of other things I've forgotten about.

Enjoy!
This is great. As far as I'm concerned there are barely (if any) public domain audio libraries such as yours. Congratulations! Two questions:

- Are you thinking in provinding an abstraction layer? I see you did some work for raylib's audio lib, but it would be nice to avoid external dependencies.
- Where does one learn to program audio software? It looks more confusing than 3D stuff.
What do you mean exactly by an abstraction layer? If you are talking about high level APIs like mixing, 3D, effects, etc. then they are planned, but a fair way away.

Regarding how to learn audio programming, I taught myself everything I know about audio programming by just browsing the internet (and I still have a lot to learn). It's not as difficult as 3D, but the platform-specific stuff is a nightmare! :)
Glad to know you are working on it. These headers lib are a godsend. Cheers.
I've just pushed version 0.9 with a lot of changes and rebrand to "miniaudio". Since the original post was so out of date I've just gone ahead and updated it with up-to-date information. Would be interested in feedback!