A new callback called `onProp` has been added to
`ma_data_source_vtable`. This replaces the following callbacks:
onGetDataFormat
onGetCursor
onGetLength
onSetLooping
This new callback is for retrieving and setting various properties
relating to the data source. It takes a `prop` parameter which is an ID
for the property being handled, and a `void*` pointer for
property-specific data.
Typically onProp implementations would discriminate on the property type
using a switch. The example below shows how to handle the old callbacks:
switch (prop)
{
// Replaces onGetDataFormat (format/channels/rate).
case MA_DATA_SOURCE_GET_DATA_SOURCE:
{
ma_data_source_data_format* pDataFormat =
(ma_data_source_data_format*)pData;
pDataFormat->format = pCustomDataSource->format;
pDataFormat->channels = pCustomDataSource->channels;
pDataFormat->sampleRate = pCustomDataSource->sampleRate;
return MA_SUCCESS;
}
// Replaces onGetDataFormat (channel map)
case MA_DATA_SOURCE_GET_CHANNEL_MAP:
{
ma_channel_map_init_standard(
ma_standard_channel_map_default,
(ma_channel*)pData,
MA_MAX_CHANNELS,
pCustomDataSource->channels);
return MA_SUCCESS;
}
// Replaces onGetCursor
case MA_DATA_SOURCE_GET_CURSOR:
{
*((ma_uint64*)pData) = pCustomDataSource->cursor;
return MA_SUCCESS;
}
// Replaces onGetLength
case MA_DATA_SOURCE_GET_LENGTH:
{
*((ma_uint64*)pData) = pCustomDataSource->length;
return MA_SUCCESS;
}
// Replaces onSetLooping
case MA_DATA_SOURCE_SET_LOOPING:
{
pCustomDataSource->isLooping = *((ma_bool32*)pData);
return MA_SUCCESS;
}
// Mandatory when MA_DATA_SOURCE_SET_LOOPING is implemented.
case MA_DATA_SOURCE_GET_LOOPING:
{
*((ma_bool32*)pData) = pCustomDataSource->isLooping;
return MA_SUCCESS;
}
// Return MA_NOT_IMPLEMENTED for any ignored properties.
default: return MA_NOT_IMPLEMENTED;
}
Note how the format/channels/rate and channel map properties have been
split across two separate properties, `MA_DATA_SOURCE_GET_DATA_SOURCE`
and `MA_DATA_SOURCE_GET_CHANNEL_MAP`. Along with this change, the
channel map parameters have been removed from
`ma_data_source_get_data_format()` and a new function called
`ma_data_source_get_channel_map()` has been added.
New properties have also been added for handling ranges and loop points.
This allows the data source implementation itself to handle it rather
than miniaudio doing it at a higher level. Where this is useful is if
your data source is a wrapper around another data source and you want to
route ranges and loop points to the internal data source.
The reason for this change is that it allows for properties to be added
without having to break the build due to yet another callback being
added. It also hides away the more niche properties that the majority of
data sources do not care about. For example, rarely does a data source
need to handle the `onSetLooping` callback, yet every data source needed
to add a `NULL` entry to their vtables just for this one extremely niche
property.
See documentation for further details.
Tag: release-notes
Tag: api-change
An audio playback and capture library in a single source file.
Features - Examples - Building - Documentation - Supported Platforms - Security - License
miniaudio is written in C with no dependencies except the standard library and should compile clean on all major compilers without the need to install any additional development packages. All major desktop and mobile platforms are supported.
Features
- Simple build system with no external dependencies.
- Simple and flexible API.
- Low-level API for direct access to raw audio data.
- High-level API for sound management, mixing, effects and optional 3D spatialization.
- Flexible node graph system for advanced mixing and effect processing.
- Resource management for loading sound files.
- Decoding, with built-in support for WAV, FLAC, and MP3, in addition to being able to plug in custom decoders.
- Encoding (WAV only).
- Data conversion.
- Resampling, including custom resamplers.
- Channel mapping.
- Basic generation of waveforms and noise.
- Basic effects and filters.
Refer to the Programming Manual for a more complete description of available features in miniaudio.
Examples
This example shows one way to play a sound using the high level API.
#include "miniaudio/miniaudio.h"
#include <stdio.h>
int main()
{
ma_result result;
ma_engine engine;
result = ma_engine_init(NULL, &engine);
if (result != MA_SUCCESS) {
return -1;
}
ma_engine_play_sound(&engine, "sound.wav", NULL);
printf("Press Enter to quit...");
getchar();
ma_engine_uninit(&engine);
return 0;
}
This example shows how to decode and play a sound using the low level API.
#include "miniaudio/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, NULL);
(void)pInput;
}
int main(int argc, char** argv)
{
ma_result result;
ma_decoder decoder;
ma_device_config deviceConfig;
ma_device device;
if (argc < 2) {
printf("No input file.\n");
return -1;
}
result = ma_decoder_init_file(argv[1], NULL, &decoder);
if (result != MA_SUCCESS) {
return -2;
}
deviceConfig = ma_device_config_init(ma_device_type_playback);
deviceConfig.playback.format = decoder.outputFormat;
deviceConfig.playback.channels = decoder.outputChannels;
deviceConfig.sampleRate = decoder.outputSampleRate;
deviceConfig.dataCallback = data_callback;
deviceConfig.pUserData = &decoder;
if (ma_device_init(NULL, &deviceConfig, &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;
}
More examples can be found in the examples folder or online here: https://miniaud.io/docs/examples/
Building
Just compile miniaudio.c like any other source file and include miniaudio.h like a normal header. 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 and -lm. On iOS you need to compile as Objective-C. Link to -ldl if you get errors about
dlopen(), etc.
If you get errors about undefined references to __sync_val_compare_and_swap_8, __atomic_load_8, etc. you
need to link with -latomic.
ABI compatibility is not guaranteed between versions so take care if compiling as a DLL/SO. The suggested way to integrate miniaudio is by adding it directly to your source tree.
You can also use CMake if that's your preference.
Documentation
Online documentation can be found here: https://miniaud.io/docs/
Documentation can also be found at the top of miniaudio.h which is always the most up-to-date and authoritative source of information on how to use miniaudio. All other documentation is generated from this in-code documentation.
Supported Platforms
- Windows
- macOS, iOS
- Linux
- FreeBSD / OpenBSD / NetBSD
- Android
- Raspberry Pi
- Emscripten / HTML5
- Dreamcast (via KallistiOS)
- Original Xbox (via NXDK)
miniaudio should compile clean on other platforms, but it will not include any support for playback or capture by default. To support that, you would need to implement a custom backend. You can do this without needing to modify the miniaudio source code. See the custom_backend example.
Backends
- WASAPI
- DirectSound
- WinMM
- Core Audio (Apple)
- PipeWire
- PulseAudio
- JACK
- ALSA
- sndio (OpenBSD)
- audio(4) (NetBSD and OpenBSD)
- OSS (FreeBSD)
- AAudio (Android 8.0+)
- OpenSL|ES (Android only)
- Web Audio (Emscripten)
- Dreamcast (via KallistiOS)
- XAudio (Original Xbox via NXDK)
- Null (Silence)
- Custom
Security
See the miniaudio security policy.
License
Your choice of either public domain or MIT No Attribution.
