mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-22 00:06:59 +02:00
Update documentation and add support for default buffer sizes and periods.
This commit is contained in:
@@ -19,10 +19,7 @@ Features
|
||||
|
||||
Examples
|
||||
========
|
||||
|
||||
Asynchonous API
|
||||
---------------
|
||||
In asynchronous mode, mini_al will request and deliver audio data through callbacks.
|
||||
mini_al will request and deliver audio data through callbacks.
|
||||
|
||||
```
|
||||
mal_uint32 on_send_audio_data(mal_device* pDevice, mal_uint32 sampleCount, void* pSamples)
|
||||
@@ -34,11 +31,11 @@ int main()
|
||||
{
|
||||
mal_uint32 channels = 2;
|
||||
mal_uint32 sampleRate = 44100;
|
||||
mal_uint32 fragmentSizeInFrames = 512;
|
||||
mal_uint32 fragmentCount = 2;
|
||||
mal_uint32 bufferSizeInFrames = 512;
|
||||
mal_uint32 periods = 2;
|
||||
|
||||
mal_device playbackDevice;
|
||||
if (mal_device_init(&playbackDevice, mal_device_type_playback, NULL, mal_format_f32, channels, sampleRate, fragmentSizeInFrames, fragmentCount) != MAL_SUCCESS) {
|
||||
if (mal_device_init(&playbackDevice, mal_device_type_playback, NULL, mal_format_f32, channels, sampleRate, bufferSizeInFrames, periods) != MAL_SUCCESS) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,23 +1,28 @@
|
||||
// Mini audio library. Public domain. See "unlicense" statement at the end of this file.
|
||||
// mini_al - v0.0 - UNRELEASED
|
||||
// mini_al - v0.1 - 2016-10-21
|
||||
//
|
||||
// David Reid - mackron@gmail.com
|
||||
|
||||
// ABOUT
|
||||
// =====
|
||||
// mini_al is a small library for making it easy to do audio playback and recording. It's focused on
|
||||
// simplicity and being light-weight so don't expect all the bells and whistles.
|
||||
// mini_al is a small library for making it easy to connect to a playback or capture device and send
|
||||
// or receive data from said device. It's focused on being simple and light-weight so don't expect
|
||||
// all the bells and whistles. Indeed, this is not a full packaged audio library - it's just for
|
||||
// connecting to a device and handling data transmission.
|
||||
//
|
||||
// mini_al uses an asynchronous API. Every device is created with it's own thread, with audio data
|
||||
// being either delivered to the application from the device (in the case of recording/capture) or
|
||||
// delivered from the application to the device in the case of playback. Synchronous APIs are not
|
||||
// supported in the interest of keeping the library as small and lightweight as possible.
|
||||
// supported in the interest of keeping the library as small and light-weight as possible.
|
||||
//
|
||||
// Supported backends:
|
||||
// - DirectSound (Windows Only)
|
||||
// - ALSA (Linux Only)
|
||||
// - null
|
||||
// - ... and many more in the future.
|
||||
// - ... and more in the future.
|
||||
// - Core Audio (OSX, iOS)
|
||||
// - Something for Android
|
||||
// - Maybe OSS
|
||||
//
|
||||
//
|
||||
// USAGE
|
||||
@@ -26,6 +31,51 @@
|
||||
// #define MAL_IMPLEMENTATION
|
||||
// #include "mini_al.h"
|
||||
//
|
||||
// You can then #include this file in other parts of the program as you would with any other header file.
|
||||
//
|
||||
//
|
||||
// Building (Windows)
|
||||
// ------------------
|
||||
// You do not need to link to anything for the Windows build, but you will need dsound.h in your include paths.
|
||||
//
|
||||
//
|
||||
// Building (Linux)
|
||||
// ----------------
|
||||
// The Linux build uses ALSA for it's backend so you will need to install the relevant ALSA development pacakges
|
||||
// for your preferred distro. It also uses pthreads.
|
||||
//
|
||||
// Linking: -lasound -lpthread
|
||||
//
|
||||
//
|
||||
// Playback Example
|
||||
// ----------------
|
||||
// mal_uint32 on_send_samples(mal_device* pDevice, mal_uint32 frameCount, void* pSamples)
|
||||
// {
|
||||
// // This callback is set with mal_device_set_send_callback() after initializing and will be
|
||||
// // called when a playback device needs more data. You need to write as many frames as you can
|
||||
// // to pSamples (but no more than frameCount) and then return the number of frames you wrote.
|
||||
// //
|
||||
// // You can pass in user data by setting pDevice->pUserData after initialization.
|
||||
// return (mal_uint32)drwav_read_f32(&wav, frameCount * pDevice->channels, (float*)pSamples) / pDevice->channels;
|
||||
// }
|
||||
//
|
||||
// ...
|
||||
//
|
||||
// mal_device device;
|
||||
// mal_result result = mal_device_init(&device, mal_device_type_playback, &id, mal_format_f32, wav.channels, wav.sampleRate, 16384, 2, NULL);
|
||||
// if (result != MAL_SUCCESS) {
|
||||
// return -1;
|
||||
// }
|
||||
//
|
||||
// device.pUserData = pMyData; // pUserData is reserved for you. Use it to pass data to callbacks.
|
||||
// mal_device_set_send_callback(&device, on_send_samples);
|
||||
// mal_device_start(&device); // The device is sleeping by default so you'll need to start it manually.
|
||||
//
|
||||
// ...
|
||||
//
|
||||
// mal_device_uninit(&device); // This will stop the device so no need to do that manually.
|
||||
//
|
||||
//
|
||||
//
|
||||
// NOTES
|
||||
// =====
|
||||
@@ -39,8 +89,34 @@
|
||||
// integer samples, interleaved. Let me know if you need non-interleaved and I'll look into it.
|
||||
//
|
||||
//
|
||||
//
|
||||
// BACKEND NUANCES
|
||||
// ===============
|
||||
// - The absolute best latency I am able to get on DirectSound is about 10 milliseconds. This seems very
|
||||
// consistent so I'm suspecting there's some kind of hard coded limit there or something.
|
||||
// - The ALSA backend does not support rewinding.
|
||||
//
|
||||
//
|
||||
//
|
||||
// OPTIONS
|
||||
// =======
|
||||
// #define these options before including this file.
|
||||
//
|
||||
// #define MAL_NO_DSOUND
|
||||
// Disables the DirectSound backend. Note that this is the only backend for the Windows platform.
|
||||
//
|
||||
// #define MAL_NO_ALSA
|
||||
// Disables the ALSA backend. Note that this is the only backend for the Linux platform.
|
||||
//
|
||||
// #define MAL_NO_NULL
|
||||
// Disables the null backend.
|
||||
//
|
||||
// #define MAL_DEFAULT_BUFFER_SIZE_IN_MILLISECONDS (Default = 15)
|
||||
// When a buffer size of 0 is specified when a device is initialized, it will default to a size with
|
||||
// this number of milliseconds worth of data.
|
||||
//
|
||||
// #define MAL_DEFAULT_PERIODS (Default = 2)
|
||||
// When a period count of 0 is specified when a device is initialized, it will default to this.
|
||||
|
||||
#ifndef mini_al_h
|
||||
#define mini_al_h
|
||||
@@ -49,6 +125,24 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Config.
|
||||
|
||||
// The default size of the device's buffer in milliseconds. In my testing, if this is a multiple of the
|
||||
// periods it can result in audio glitching on the DirectSound backend, so make sure it's not a clean
|
||||
// multiple of the period.
|
||||
//
|
||||
// If this is too small you may get underruns and overruns in which case you'll need to either increase
|
||||
// this value or use an explicit buffer size.
|
||||
#ifndef MAL_DEFAULT_BUFFER_SIZE_IN_MILLISECONDS
|
||||
#define MAL_DEFAULT_BUFFER_SIZE_IN_MILLISECONDS 15
|
||||
#endif
|
||||
|
||||
// Default periods when none is specified in mal_device_init(). More periods means more work on the CPU.
|
||||
#ifndef MAL_DEFAULT_PERIODS
|
||||
#define MAL_DEFAULT_PERIODS 2
|
||||
#endif
|
||||
|
||||
|
||||
// Platform/backend detection.
|
||||
#ifdef _WIN32
|
||||
#define MAL_WIN32
|
||||
@@ -111,10 +205,6 @@ typedef void* mal_ptr;
|
||||
} mal_event;
|
||||
#endif
|
||||
|
||||
#ifdef MAL_ENABLE_DSOUND
|
||||
#define MAL_MAX_PERIODS_DSOUND 16
|
||||
#endif
|
||||
|
||||
typedef int mal_result;
|
||||
#define MAL_SUCCESS 0
|
||||
#define MAL_ERROR -1 // A generic error.
|
||||
@@ -278,16 +368,22 @@ struct mal_device
|
||||
// This API dynamically links to backend DLLs/SOs (such as dsound.dll).
|
||||
mal_result mal_enumerate_devices(mal_device_type type, mal_uint32* pCount, mal_device_info* pInfo);
|
||||
|
||||
// Initializes a device in asynchronous mode.
|
||||
// Initializes a device.
|
||||
//
|
||||
// The device ID (pDeviceID) can be null, in which case the default device is used. Otherwise, you
|
||||
// can retrieve the ID by calling mal_enumerate_devices() and retrieve the ID from the returned
|
||||
// information.
|
||||
// can retrieve the ID by calling mal_enumerate_devices() and using the ID from the returned data.
|
||||
//
|
||||
// This will try it's hardest to create a valid device, even if it means adjusting input arguments.
|
||||
// Look at pDevice->channels, pDevice->sampleRate, etc. to determine the actual properties after
|
||||
// initialization.
|
||||
//
|
||||
// If <bufferSizeInFrames> is 0, it will default to MAL_DEFAULT_BUFFER_SIZE_IN_MILLISECONDS. If
|
||||
// <periods> is set to 0 it will default to MAL_DEFAULT_PERIODS.
|
||||
//
|
||||
// The <periods> property controls how frequently the background thread is woken to check for more
|
||||
// data. It's tied to the buffer size, so as an example, if your buffer size is equivalent to 10
|
||||
// milliseconds and you have 2 periods, the CPU will wake up approximately every 5 milliseconds.
|
||||
//
|
||||
// Return Value:
|
||||
// - MAL_SUCCESS if successful.
|
||||
// - MAL_INVALID_ARGS
|
||||
@@ -299,14 +395,13 @@ mal_result mal_enumerate_devices(mal_device_type type, mal_uint32* pCount, mal_d
|
||||
// that performs a memory allocation is ALSA when mmap mode is not supported.
|
||||
// - MAL_FORMAT_NOT_SUPPORTED
|
||||
// The specified format is not supported by the backend. mini_al does not currently do any
|
||||
// software format conversions which means initialization must fail if the backend device does
|
||||
// not natively support it.
|
||||
// software format conversions which means initialization must fail if the backend does not
|
||||
// natively support it.
|
||||
// - MAL_FAILED_TO_INIT_BACKEND
|
||||
// There was a backend-specific error during initialization.
|
||||
//
|
||||
// Thread Safety: ???
|
||||
// This API is thread safe so long as the application does not try to use the device object before
|
||||
// this call has returned.
|
||||
// Thread Safety: UNSAFE
|
||||
// Results are undefined if you try using a device before this function as returned.
|
||||
//
|
||||
// Efficiency: LOW
|
||||
// This API will dynamically link to backend DLLs/SOs like dsound.dll, and is otherwise just slow
|
||||
@@ -1508,9 +1603,6 @@ static mal_result mal_device_init__dsound(mal_device* pDevice, mal_device_type t
|
||||
return MAL_FORMAT_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
if (periods > MAL_MAX_PERIODS_DSOUND) {
|
||||
periods = MAL_MAX_PERIODS_DSOUND;
|
||||
}
|
||||
|
||||
WAVEFORMATEXTENSIBLE wf;
|
||||
mal_zero_object(&wf);
|
||||
@@ -1583,6 +1675,7 @@ static mal_result mal_device_init__dsound(mal_device* pDevice, mal_device_type t
|
||||
pDevice->sampleRate = pActualFormat->Format.nSamplesPerSec;
|
||||
bufferSizeInBytes = pDevice->bufferSizeInFrames * pDevice->channels * mal_get_sample_size_in_bytes(pDevice->format);
|
||||
|
||||
|
||||
// Meaning of dwFlags (from MSDN):
|
||||
//
|
||||
// DSBCAPS_GLOBALFOCUS
|
||||
@@ -2774,7 +2867,11 @@ mal_result mal_device_init(mal_device* pDevice, mal_device_type type, mal_device
|
||||
}
|
||||
}
|
||||
|
||||
if (channels == 0 || sampleRate == 0 || bufferSizeInFrames == 0 || periods == 0) return mal_post_error(pDevice, "mal_device_init() called with invalid arguments.", MAL_INVALID_ARGS);
|
||||
if (channels == 0 || sampleRate == 0) return mal_post_error(pDevice, "mal_device_init() called with invalid arguments.", MAL_INVALID_ARGS);
|
||||
|
||||
// Default buffer size and periods.
|
||||
if (bufferSizeInFrames == 0) bufferSizeInFrames = (sampleRate/1000) * MAL_DEFAULT_BUFFER_SIZE_IN_MILLISECONDS;
|
||||
if (periods == 0) periods = MAL_DEFAULT_PERIODS;
|
||||
|
||||
pDevice->type = type;
|
||||
pDevice->format = format;
|
||||
@@ -3087,7 +3184,7 @@ mal_uint32 mal_get_sample_size_in_bytes(mal_format format)
|
||||
// REVISION HISTORY
|
||||
// ================
|
||||
//
|
||||
// v0.1 - TBD
|
||||
// v0.1 - 2016-10-21
|
||||
// - Initial versioned release.
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user