Commit 3e79be29 authored by mathieu _alkama_ m's avatar mathieu _alkama_ m Committed by Gargaj
Browse files

mini_al is now miniaudio

Also fixes the problem with VS2019 in Release mode by replacing ZeroMemory with SecureZeroMemory
parent dd6b0840
......@@ -118,8 +118,8 @@ set(BZC_PROJECT_INCLUDES ${BZC_PROJECT_INCLUDES}
)
##############################################################################
# mini_al
set(BZC_PROJECT_INCLUDES ${BZC_PROJECT_INCLUDES} ${CMAKE_SOURCE_DIR}/external/mini_al)
# miniaudio
set(BZC_PROJECT_INCLUDES ${BZC_PROJECT_INCLUDES} ${CMAKE_SOURCE_DIR}/external/miniaudio)
##############################################################################
# kiss_fft
......
This diff is collapsed.
![mini_al](http://dred.io/img/minial_wide.png)
![miniaudio](http://dred.io/img/miniaudio_wide.png)
mini_al is a single file library for audio playback and capture. It's written in C (compilable as C++)
and released into the public domain.
miniaudio (formerly mini_al) is a single file library for audio playback and capture. It's written
in C (compilable as C++) and released into the public domain.
Features
......@@ -9,7 +9,7 @@ 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 both playback and capture on all backends.
- Supports playback, capture and full-duplex.
- Data conversion.
- Sample format conversion, with optional dithering.
- Sample rate conversion.
......@@ -41,9 +41,9 @@ Backends
- sndio (OpenBSD)
- audio(4) (NetBSD and OpenBSD)
- OSS (FreeBSD)
- AAudio (Android 8.0+)
- OpenSL|ES (Android only)
- OpenAL
- SDL
- Web Audio (Emscripten)
- Null (Silence)
......@@ -51,8 +51,8 @@ Building
======
Do the following in one source file:
```
#define MINI_AL_IMPLEMENTATION
#include "mini_al.h"
#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.
......@@ -69,20 +69,21 @@ Simple Playback Example
#define DR_WAV_IMPLEMENTATION
#include "../extras/dr_wav.h" // Enables WAV decoding.
#define MINI_AL_IMPLEMENTATION
#include "../mini_al.h"
#define MINIAUDIO_IMPLEMENTATION
#include "../miniaudio.h"
#include <stdio.h>
// This is the function that's used for sending more data to the device for playback.
mal_uint32 on_send_frames_to_device(mal_device* pDevice, mal_uint32 frameCount, void* pSamples)
void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount)
{
mal_decoder* pDecoder = (mal_decoder*)pDevice->pUserData;
ma_decoder* pDecoder = (ma_decoder*)pDevice->pUserData;
if (pDecoder == NULL) {
return 0;
return;
}
return (mal_uint32)mal_decoder_read(pDecoder, frameCount, pSamples);
ma_decoder_read_pcm_frames(pDecoder, pOutput, frameCount);
(void)pInput;
}
int main(int argc, char** argv)
......@@ -92,37 +93,38 @@ int main(int argc, char** argv)
return -1;
}
mal_decoder decoder;
mal_result result = mal_decoder_init_file(argv[1], NULL, &decoder);
if (result != MAL_SUCCESS) {
ma_decoder decoder;
ma_result result = ma_decoder_init_file(argv[1], NULL, &decoder);
if (result != MA_SUCCESS) {
return -2;
}
mal_device_config config = mal_device_config_init_playback(
decoder.outputFormat,
decoder.outputChannels,
decoder.outputSampleRate,
on_send_frames_to_device);
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;
mal_device device;
if (mal_device_init(NULL, mal_device_type_playback, NULL, &config, &decoder, &device) != MAL_SUCCESS) {
ma_device device;
if (ma_device_init(NULL, &config, &device) != MA_SUCCESS) {
printf("Failed to open playback device.\n");
mal_decoder_uninit(&decoder);
ma_decoder_uninit(&decoder);
return -3;
}
if (mal_device_start(&device) != MAL_SUCCESS) {
if (ma_device_start(&device) != MA_SUCCESS) {
printf("Failed to start playback device.\n");
mal_device_uninit(&device);
mal_decoder_uninit(&decoder);
ma_device_uninit(&device);
ma_decoder_uninit(&decoder);
return -4;
}
printf("Press Enter to quit...");
getchar();
mal_device_uninit(&device);
mal_decoder_uninit(&decoder);
ma_device_uninit(&device);
ma_decoder_uninit(&decoder);
return 0;
}
......@@ -131,53 +133,53 @@ int main(int argc, char** argv)
MP3/Vorbis/FLAC/WAV Decoding
============================
mini_al includes a decoding API which supports the following backends:
miniaudio includes a decoding API which supports the following backends:
- FLAC via [dr_flac](https://github.com/mackron/dr_libs/blob/master/dr_flac.h)
- MP3 via [dr_mp3](https://github.com/mackron/dr_libs/blob/master/dr_mp3.h)
- WAV via [dr_wav](https://github.com/mackron/dr_libs/blob/master/dr_wav.h)
- Vorbis via [stb_vorbis](https://github.com/nothings/stb/blob/master/stb_vorbis.c)
Copies of these libraries can be found in the "extras" folder. You may also want to look at the
libraries below, but they are not supported by the mini_al decoder API. If you know of any other
libraries below, but they are not supported by the miniaudio decoder API. If you know of any other
single file libraries I can add to this list, let me know. Preferably public domain or MIT.
- [minimp3](https://github.com/lieff/minimp3)
- [jar_mod](https://github.com/kd7tck/jar/blob/master/jar_mod.h)
- [jar_xm](https://github.com/kd7tck/jar/blob/master/jar_xm.h)
To enable support for a decoding backend, all you need to do is #include the header section of the
relevant backend library before the implementation of mini_al, like so:
relevant backend library before the implementation of miniaudio, like so:
```
#include "dr_flac.h" // Enables FLAC decoding.
#include "dr_mp3.h" // Enables MP3 decoding.
#include "dr_wav.h" // Enables WAV decoding.
#define MINI_AL_IMPLEMENTATION
#include "mini_al.h"
#define MINIAUDIO_IMPLEMENTATION
#include "miniaudio.h"
```
A decoder can be initialized from a file with `mal_decoder_init_file()`, a block of memory with
`mal_decoder_init_memory()`, or from data delivered via callbacks with `mal_decoder_init()`. Here
A decoder can be initialized from a file with `ma_decoder_init_file()`, a block of memory with
`ma_decoder_init_memory()`, or from data delivered via callbacks with `ma_decoder_init()`. Here
is an example for loading a decoder from a file:
```
mal_decoder decoder;
mal_result result = mal_decoder_init_file("MySong.mp3", NULL, &decoder);
if (result != MAL_SUCCESS) {
ma_decoder decoder;
ma_result result = ma_decoder_init_file("MySong.mp3", NULL, &decoder);
if (result != MA_SUCCESS) {
return false; // An error occurred.
}
...
mal_decoder_uninit(&decoder);
ma_decoder_uninit(&decoder);
```
When initializing a decoder, you can optionally pass in a pointer to a `mal_decoder_config` object
When initializing a decoder, you can optionally pass in a pointer to a `ma_decoder_config` object
(the `NULL` argument in the example above) which allows you to configure the output format, channel
count, sample rate and channel map:
```
mal_decoder_config config = mal_decoder_config_init(mal_format_f32, 2, 48000);
ma_decoder_config config = ma_decoder_config_init(ma_format_f32, 2, 48000);
```
When passing in NULL for this parameter, the output format will be the same as that defined by the
......@@ -186,31 +188,31 @@ decoding backend.
Data is read from the decoder as PCM frames:
```
mal_uint64 framesRead = mal_decoder_read(pDecoder, framesToRead, pFrames);
ma_uint64 framesRead = ma_decoder_read_pcm_frames(pDecoder, pFrames, framesToRead);
```
You can also seek to a specific frame like so:
```
mal_result result = mal_decoder_seek(pDecoder, targetFrame);
if (result != MAL_SUCCESS) {
ma_result result = ma_decoder_seek_to_pcm_frame(pDecoder, targetFrame);
if (result != MA_SUCCESS) {
return false; // An error occurred.
}
```
When loading a decoder, mini_al uses a trial and error technique to find the appropriate decoding
When loading a decoder, miniaudio uses a trial and error technique to find the appropriate decoding
backend. This can be unnecessarily inefficient if the type is already known. In this case you can
use the `_wav`, `_mp3`, etc. varients of the aforementioned initialization APIs:
```
mal_decoder_init_wav()
mal_decoder_init_mp3()
mal_decoder_init_memory_wav()
mal_decoder_init_memory_mp3()
mal_decoder_init_file_wav()
mal_decoder_init_file_mp3()
ma_decoder_init_wav()
ma_decoder_init_mp3()
ma_decoder_init_memory_wav()
ma_decoder_init_memory_mp3()
ma_decoder_init_file_wav()
ma_decoder_init_file_mp3()
etc.
```
The `mal_decoder_init_file()` API will try using the file extension to determine which decoding
The `ma_decoder_init_file()` API will try using the file extension to determine which decoding
backend to prefer.
This diff is collapsed.
#define MINI_AL_IMPLEMENTATION
#include <mini_al.h>
#define MINIAUDIO_IMPLEMENTATION
#include <miniaudio.h>
#include <kiss_fft.h>
#include <kiss_fftr.h>
......@@ -10,22 +10,22 @@
namespace FFT
{
kiss_fftr_cfg fftcfg;
mal_context context;
mal_device captureDevice;
ma_context context;
ma_device captureDevice;
float sampleBuf[ FFT_SIZE * 2 ];
float fAmplification = 1.0f;
void OnLog( mal_context* pContext, mal_device* pDevice, const char* message )
void OnLog( ma_context* pContext, ma_device* pDevice, ma_uint32 logLevel, const char* message )
{
printf( "[FFT] [mal:%p:%p]\n %s", pContext, pDevice, message );
}
void OnReceiveFrames( mal_device* pDevice, mal_uint32 frameCount, const void* pSamples )
void OnReceiveFrames( ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount )
{
frameCount = frameCount < FFT_SIZE * 2 ? frameCount : FFT_SIZE * 2;
// Just rotate the buffer; copy existing, append new
const float * samples = (const float *)pSamples;
const float * samples = (const float *)pInput;
float * p = sampleBuf;
for ( int i = 0; i < FFT_SIZE * 2 - frameCount; i++ )
{
......@@ -43,31 +43,38 @@ namespace FFT
fftcfg = kiss_fftr_alloc( FFT_SIZE * 2, false, NULL, NULL );
const mal_context_config context_config = mal_context_config_init( OnLog );
mal_result result = mal_context_init( NULL, 0, &context_config, &context );
if ( result != MAL_SUCCESS )
ma_context_config context_config = ma_context_config_init();
context_config.logCallback = OnLog;
ma_result result = ma_context_init( NULL, 0, &context_config, &context );
if ( result != MA_SUCCESS )
{
printf( "[FFT] Failed to initialize context: %d", result );
return false;
}
printf( "[FFT] MAL context initialized, backend is '%s'\n", mal_get_backend_name( context.backend ) );
printf( "[FFT] MAL context initialized, backend is '%s'\n", ma_get_backend_name( context.backend ) );
const mal_device_config config = mal_device_config_init( mal_format_f32, 2, 44100, OnReceiveFrames, NULL );
result = mal_device_init( &context, mal_device_type_capture, NULL, &config, NULL, &captureDevice );
if ( result != MAL_SUCCESS )
ma_device_config config = ma_device_config_init( ma_device_type_capture );
config.capture.pDeviceID = NULL;
config.capture.format = ma_format_f32;
config.capture.channels = 2;
config.sampleRate = 44100;
config.dataCallback = OnReceiveFrames;
config.pUserData = NULL;
result = ma_device_init( &context, &config, &captureDevice );
if ( result != MA_SUCCESS )
{
mal_context_uninit( &context );
ma_context_uninit( &context );
printf( "[FFT] Failed to initialize capture device: %d\n", result );
return false;
}
result = mal_device_start( &captureDevice );
if ( result != MAL_SUCCESS )
result = ma_device_start( &captureDevice );
if ( result != MA_SUCCESS )
{
mal_device_uninit( &captureDevice );
mal_context_uninit( &context );
ma_device_uninit( &captureDevice );
ma_context_uninit( &context );
printf( "[FFT] Failed to start capture device: %d\n", result );
return false;
}
......@@ -89,10 +96,10 @@ namespace FFT
}
void Close()
{
mal_device_stop( &captureDevice );
ma_device_stop( &captureDevice );
mal_device_uninit( &captureDevice );
mal_context_uninit( &context );
ma_device_uninit( &captureDevice );
ma_context_uninit( &context );
kiss_fft_free( fftcfg );
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment