Update examples to C89.

This commit is contained in:
David Reid
2019-05-05 19:03:26 +10:00
parent 2fcb2b9ae7
commit 971eb610c0
11 changed files with 231 additions and 187 deletions
+122 -94
View File
@@ -16,7 +16,7 @@ void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uin
(void)pOutput; (void)pOutput;
(void)pInput; (void)pInput;
(void)frameCount; (void)frameCount;
return; // Just output silence for this example. return; /* Just output silence for this example. */
} }
void stop_callback(ma_device* pDevice) void stop_callback(ma_device* pDevice)
@@ -27,63 +27,24 @@ void stop_callback(ma_device* pDevice)
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
(void)argc; ma_result result;
(void)argv; ma_context_config contextConfig;
ma_context context;
ma_device_config deviceConfig;
ma_device playbackDevice;
ma_device_info* pPlaybackDeviceInfos;
ma_uint32 playbackDeviceCount;
ma_device_info* pCaptureDeviceInfos;
ma_uint32 captureDeviceCount;
ma_uint32 iDevice;
// When initializing a context, you can pass in an optional configuration object that allows you to control /*
// context-level configuration. The ma_context_config_init() function will initialize a config object with The prioritization of backends can be controlled by the application. You need only specify the backends
// common configuration settings, but you can set other members for more detailed control. you care about. If the context cannot be initialized for any of the specified backends ma_context_init()
ma_context_config contextConfig = ma_context_config_init(); will fail.
contextConfig.logCallback = log_callback; */
// The priority of the worker thread can be set with the following. The default priority is
// ma_thread_priority_highest.
contextConfig.threadPriority = ma_thread_priority_normal;
// PulseAudio
// ----------
// PulseAudio allows you to set the name of the application. miniaudio exposes this through the following
// config.
contextConfig.pulse.pApplicationName = "My Application";
// PulseAudio also allows you to control the server you want to connect to, in which case you can specify
// it with the config below.
contextConfig.pulse.pServerName = "my_server";
// During initialization, PulseAudio can try to automatically start the PulseAudio daemon. This does not
// suit miniaudio's trial and error backend initialization architecture so it's disabled by default, but you
// can enable it like so:
contextConfig.pulse.tryAutoSpawn = MA_TRUE;
// ALSA
// ----
// Typically, ALSA enumerates many devices, which unfortunately is not very friendly for the end user. To
// combat this, miniaudio will include only unique card/device pairs by default. The problem with this is that
// you lose a bit of flexibility and control. Setting alsa.useVerboseDeviceEnumeration makes it so the ALSA
// backend includes all devices (and there's a lot of them!).
contextConfig.alsa.useVerboseDeviceEnumeration = MA_TRUE;
// JACK
// ----
// Like PulseAudio, JACK allows you to specify the name of your application, which you can set like so:
contextConfig.jack.pClientName = "My Application";
// Also like PulseAudio, you can have JACK try to automatically start using the following:
contextConfig.jack.tryStartServer = MA_TRUE;
// The prioritization of backends can be controlled by the application. You need only specify the backends
// you care about. If the context cannot be initialized for any of the specified backends ma_context_init()
// will fail.
ma_backend backends[] = { ma_backend backends[] = {
ma_backend_wasapi, // Higest priority. ma_backend_wasapi, /* Higest priority. */
ma_backend_dsound, ma_backend_dsound,
ma_backend_winmm, ma_backend_winmm,
ma_backend_coreaudio, ma_backend_coreaudio,
@@ -96,92 +57,156 @@ int main(int argc, char** argv)
ma_backend_aaudio, ma_backend_aaudio,
ma_backend_opensl, ma_backend_opensl,
ma_backend_webaudio, ma_backend_webaudio,
ma_backend_null // Lowest priority. ma_backend_null /* Lowest priority. */
}; };
ma_context context;
/*
When initializing a context, you can pass in an optional configuration object that allows you to control
context-level configuration. The ma_context_config_init() function will initialize a config object with
common configuration settings, but you can set other members for more detailed control.
*/
contextConfig = ma_context_config_init();
contextConfig.logCallback = log_callback;
/*
The priority of the worker thread can be set with the following. The default priority is
ma_thread_priority_highest.
*/
contextConfig.threadPriority = ma_thread_priority_normal;
/* PulseAudio */
/* PulseAudio allows you to set the name of the application. miniaudio exposes this through the following config. */
contextConfig.pulse.pApplicationName = "My Application";
/*
PulseAudio also allows you to control the server you want to connect to, in which case you can specify
it with the config below.
*/
contextConfig.pulse.pServerName = "my_server";
/*
During initialization, PulseAudio can try to automatically start the PulseAudio daemon. This does not
suit miniaudio's trial and error backend initialization architecture so it's disabled by default, but you
can enable it like so:
*/
contextConfig.pulse.tryAutoSpawn = MA_TRUE;
/* ALSA */
/*
Typically, ALSA enumerates many devices, which unfortunately is not very friendly for the end user. To
combat this, miniaudio will include only unique card/device pairs by default. The problem with this is that
you lose a bit of flexibility and control. Setting alsa.useVerboseDeviceEnumeration makes it so the ALSA
backend includes all devices (and there's a lot of them!).
*/
contextConfig.alsa.useVerboseDeviceEnumeration = MA_TRUE;
/* JACK */
/* Like PulseAudio, JACK allows you to specify the name of your application, which you can set like so: */
contextConfig.jack.pClientName = "My Application";
/* Also like PulseAudio, you can have JACK try to automatically start using the following: */
contextConfig.jack.tryStartServer = MA_TRUE;
if (ma_context_init(backends, sizeof(backends)/sizeof(backends[0]), &contextConfig, &context) != MA_SUCCESS) { if (ma_context_init(backends, sizeof(backends)/sizeof(backends[0]), &contextConfig, &context) != MA_SUCCESS) {
printf("Failed to initialize context."); printf("Failed to initialize context.");
return -2; return -2;
} }
// Enumerate devices. /* Enumerate devices. */
ma_device_info* pPlaybackDeviceInfos; result = ma_context_get_devices(&context, &pPlaybackDeviceInfos, &playbackDeviceCount, &pCaptureDeviceInfos, &captureDeviceCount);
ma_uint32 playbackDeviceCount;
ma_device_info* pCaptureDeviceInfos;
ma_uint32 captureDeviceCount;
ma_result result = ma_context_get_devices(&context, &pPlaybackDeviceInfos, &playbackDeviceCount, &pCaptureDeviceInfos, &captureDeviceCount);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
printf("Failed to retrieve device information.\n"); printf("Failed to retrieve device information.\n");
return -3; return -3;
} }
printf("Playback Devices (%d)\n", playbackDeviceCount); printf("Playback Devices (%d)\n", playbackDeviceCount);
for (ma_uint32 iDevice = 0; iDevice < playbackDeviceCount; ++iDevice) { for (iDevice = 0; iDevice < playbackDeviceCount; ++iDevice) {
printf(" %u: %s\n", iDevice, pPlaybackDeviceInfos[iDevice].name); printf(" %u: %s\n", iDevice, pPlaybackDeviceInfos[iDevice].name);
} }
printf("\n"); printf("\n");
printf("Capture Devices (%d)\n", captureDeviceCount); printf("Capture Devices (%d)\n", captureDeviceCount);
for (ma_uint32 iDevice = 0; iDevice < captureDeviceCount; ++iDevice) { for (iDevice = 0; iDevice < captureDeviceCount; ++iDevice) {
printf(" %u: %s\n", iDevice, pCaptureDeviceInfos[iDevice].name); printf(" %u: %s\n", iDevice, pCaptureDeviceInfos[iDevice].name);
} }
// Open the device. /*
// Open the device.
// Unlike context configs, device configs are required. Similar to context configs, an API exists to help you
// initialize a config object called ma_device_config_init(). Unlike context configs, device configs are required. Similar to context configs, an API exists to help you
// initialize a config object called ma_device_config_init().
// When using full-duplex you may want to use a different sample format, channel count and channel map. To
// support this, the device configuration splits these into "playback" and "capture" as shown below. When using full-duplex you may want to use a different sample format, channel count and channel map. To
ma_device_config deviceConfig = ma_device_config_init(ma_device_type_playback); support this, the device configuration splits these into "playback" and "capture" as shown below.
*/
deviceConfig = ma_device_config_init(ma_device_type_playback);
deviceConfig.playback.format = ma_format_s16; deviceConfig.playback.format = ma_format_s16;
deviceConfig.playback.channels = 2; deviceConfig.playback.channels = 2;
deviceConfig.sampleRate = 48000; deviceConfig.sampleRate = 48000;
deviceConfig.dataCallback = data_callback; deviceConfig.dataCallback = data_callback;
deviceConfig.pUserData = NULL; deviceConfig.pUserData = NULL;
// Applications can specify a callback for when a device is stopped. /* Applications can specify a callback for when a device is stopped. */
deviceConfig.stopCallback = stop_callback; deviceConfig.stopCallback = stop_callback;
// Applications can request exclusive control of the device using the config variable below. Note that not all /*
// backends support this feature, so this is actually just a hint. Applications can request exclusive control of the device using the config variable below. Note that not all
backends support this feature, so this is actually just a hint.
*/
deviceConfig.playback.shareMode = ma_share_mode_exclusive; deviceConfig.playback.shareMode = ma_share_mode_exclusive;
// miniaudio allows applications to control the mapping of channels. The config below swaps the left and right /*
// channels. Normally in an interleaved audio stream, the left channel comes first, but we can change that miniaudio allows applications to control the mapping of channels. The config below swaps the left and right
// like the following: channels. Normally in an interleaved audio stream, the left channel comes first, but we can change that
like the following:
*/
deviceConfig.playback.channelMap[0] = MA_CHANNEL_FRONT_RIGHT; deviceConfig.playback.channelMap[0] = MA_CHANNEL_FRONT_RIGHT;
deviceConfig.playback.channelMap[1] = MA_CHANNEL_FRONT_LEFT; deviceConfig.playback.channelMap[1] = MA_CHANNEL_FRONT_LEFT;
// The ALSA backend has two ways of delivering data to and from a device: memory mapping and read/write. By /*
// default memory mapping will be used over read/write because it avoids a single point of data movement The ALSA backend has two ways of delivering data to and from a device: memory mapping and read/write. By
// internally and is thus, theoretically, more efficient. In testing, however, this has been less stable than default memory mapping will be used over read/write because it avoids a single point of data movement
// read/write mode so an option exists to disable it if need be. This is mainly for debugging, but is left internally and is thus, theoretically, more efficient. In testing, however, this has been less stable than
// here in case it might be useful for others. If you find a bug specific to mmap mode, please report it! read/write mode so an option exists to disable it if need be. This is mainly for debugging, but is left
here in case it might be useful for others. If you find a bug specific to mmap mode, please report it!
*/
deviceConfig.alsa.noMMap = MA_TRUE; deviceConfig.alsa.noMMap = MA_TRUE;
// This is not used in this example, but miniaudio allows you to directly control the device ID that's used /*
// for device selection by ma_device_init(). Below is an example for ALSA. In this example it forces This is not used in this example, but miniaudio allows you to directly control the device ID that's used
// ma_device_init() to try opening the "hw:0,0" device. This is useful for debugging in case you have for device selection by ma_device_init(). Below is an example for ALSA. In this example it forces
// audio glitches or whatnot with specific devices. ma_device_init() to try opening the "hw:0,0" device. This is useful for debugging in case you have
audio glitches or whatnot with specific devices.
*/
#ifdef MA_SUPPORT_ALSA #ifdef MA_SUPPORT_ALSA
{
ma_device_id customDeviceID; ma_device_id customDeviceID;
if (context.backend == ma_backend_alsa) { if (context.backend == ma_backend_alsa) {
strcpy(customDeviceID.alsa, "hw:0,0"); strcpy(customDeviceID.alsa, "hw:0,0");
// The ALSA backend also supports a miniaudio-specific format which looks like this: ":0,0". In this case, /*
// miniaudio will try different plugins depending on the shareMode setting. When using shared mode it will The ALSA backend also supports a miniaudio-specific format which looks like this: ":0,0". In this case,
// convert ":0,0" to "dmix:0,0"/"dsnoop:0,0". For exclusive mode (or if dmix/dsnoop fails) it will convert miniaudio will try different plugins depending on the shareMode setting. When using shared mode it will
// it to "hw:0,0". This is how the ALSA backend honors the shareMode hint. convert ":0,0" to "dmix:0,0"/"dsnoop:0,0". For exclusive mode (or if dmix/dsnoop fails) it will convert
it to "hw:0,0". This is how the ALSA backend honors the shareMode hint.
*/
strcpy(customDeviceID.alsa, ":0,0"); strcpy(customDeviceID.alsa, ":0,0");
} }
}
#endif #endif
ma_device playbackDevice;
if (ma_device_init(&context, &deviceConfig, &playbackDevice) != MA_SUCCESS) { if (ma_device_init(&context, &deviceConfig, &playbackDevice) != MA_SUCCESS) {
printf("Failed to initialize playback device.\n"); printf("Failed to initialize playback device.\n");
ma_context_uninit(&context); ma_context_uninit(&context);
@@ -202,5 +227,8 @@ int main(int argc, char** argv)
ma_context_uninit(&context); ma_context_uninit(&context);
(void)argc;
(void)argv;
return 0; return 0;
} }
+6 -6
View File
@@ -1,6 +1,6 @@
cc ../simple_playback.c -o ../bin/simple_playback -Wall -Wpedantic -std=c99 -lpthread -lm cc ../simple_playback.c -o ../bin/simple_playback -Wall -Wpedantic -std=c89 -ansi -pedantic -lpthread -lm
cc ../simple_capture.c -o ../bin/simple_capture -Wall -Wpedantic -std=c99 -lpthread -lm cc ../simple_capture.c -o ../bin/simple_capture -Wall -Wpedantic -std=c89 -ansi -pedantic -lpthread -lm
cc ../simple_enumeration.c -o ../bin/simple_enumeration -Wall -Wpedantic -std=c99 -lpthread -lm cc ../simple_enumeration.c -o ../bin/simple_enumeration -Wall -Wpedantic -std=c89 -ansi -pedantic -lpthread -lm
cc ../simple_mixing.c -o ../bin/simple_mixing -Wall -Wpedantic -std=c99 -lpthread -lm cc ../simple_mixing.c -o ../bin/simple_mixing -Wall -Wpedantic -std=c89 -ansi -pedantic -lpthread -lm
cc ../simple_playback_emscripten.c -o ../bin/simple_playback_emscripten -Wall -Wpedantic -std=c99 -lpthread -lm cc ../simple_playback_emscripten.c -o ../bin/simple_playback_emscripten -Wall -Wpedantic -std=c89 -ansi -pedantic -lpthread -lm
cc ../advanced_config.c -o ../bin/advanced_config -Wall -Wpedantic -std=c99 -lpthread -lm cc ../advanced_config.c -o ../bin/advanced_config -Wall -Wpedantic -std=c89 -ansi -pedantic -lpthread -lm
@@ -1 +1 @@
emcc ../simple_playback_emscripten.c -o ../bin/simple_playback_emscripten.html emcc ../simple_playback_emscripten.c -o ../bin/simple_playback_emscripten.html -std=c89 -ansi -Wall
+6 -6
View File
@@ -1,6 +1,6 @@
cc ../simple_playback.c -o ../bin/simple_playback -Wall -Wpedantic -std=c99 -lpthread -ldl -lm cc ../simple_playback.c -o ../bin/simple_playback -Wall -Wpedantic -std=c89 -ansi -pedantic -lpthread -ldl -lm
cc ../simple_capture.c -o ../bin/simple_capture -Wall -Wpedantic -std=c99 -lpthread -ldl -lm cc ../simple_capture.c -o ../bin/simple_capture -Wall -Wpedantic -std=c89 -ansi -pedantic -lpthread -ldl -lm
cc ../simple_enumeration.c -o ../bin/simple_enumeration -Wall -Wpedantic -std=c99 -lpthread -ldl -lm cc ../simple_enumeration.c -o ../bin/simple_enumeration -Wall -Wpedantic -std=c89 -ansi -pedantic -lpthread -ldl -lm
cc ../simple_mixing.c -o ../bin/simple_mixing -Wall -Wpedantic -std=c99 -lpthread -ldl -lm cc ../simple_mixing.c -o ../bin/simple_mixing -Wall -Wpedantic -std=c89 -ansi -pedantic -lpthread -ldl -lm
cc ../simple_playback_emscripten.c -o ../bin/simple_playback_emscripten -Wall -Wpedantic -std=c99 -lpthread -ldl -lm cc ../simple_playback_emscripten.c -o ../bin/simple_playback_emscripten -Wall -Wpedantic -std=c89 -ansi -pedantic -lpthread -ldl -lm
cc ../advanced_config.c -o ../bin/advanced_config -Wall -Wpedantic -std=c99 -lpthread -ldl -lm cc ../advanced_config.c -o ../bin/advanced_config -Wall -Wpedantic -std=c89 -ansi -pedantic -lpthread -ldl -lm
+6 -6
View File
@@ -1,6 +1,6 @@
cc ../simple_playback.c -o ../bin/simple_playback -Wall -Wpedantic -std=c99 -lpthread -lm cc ../simple_playback.c -o ../bin/simple_playback -Wall -Wpedantic -std=c89 -ansi -pedantic -lpthread -lm
cc ../simple_capture.c -o ../bin/simple_capture -Wall -Wpedantic -std=c99 -lpthread -lm cc ../simple_capture.c -o ../bin/simple_capture -Wall -Wpedantic -std=c89 -ansi -pedantic -lpthread -lm
cc ../simple_enumeration.c -o ../bin/simple_enumeration -Wall -Wpedantic -std=c99 -lpthread -lm cc ../simple_enumeration.c -o ../bin/simple_enumeration -Wall -Wpedantic -std=c89 -ansi -pedantic -lpthread -lm
cc ../advanced_config.c -o ../bin/advanced_config -Wall -Wpedantic -std=c99 -lpthread -lm cc ../advanced_config.c -o ../bin/advanced_config -Wall -Wpedantic -std=c89 -ansi -pedantic -lpthread -lm
cc ../simple_mixing.c -o ../bin/simple_mixing -Wall -Wpedantic -std=c99 -lpthread -lm cc ../simple_mixing.c -o ../bin/simple_mixing -Wall -Wpedantic -std=c89 -ansi -pedantic -lpthread -lm
cc ../simple_playback_emscripten.c -o ../bin/simple_playback_emscripten -Wall -Wpedantic -std=c99 -lpthread -lm cc ../simple_playback_emscripten.c -o ../bin/simple_playback_emscripten -Wall -Wpedantic -std=c89 -ansi -pedantic -lpthread -lm
+3 -1
View File
@@ -1,10 +1,12 @@
@echo off @echo off
SET c_compiler=gcc SET c_compiler=gcc
SET cpp_compiler=g++ SET cpp_compiler=g++
SET options=-Wall -Wpedantic -std=c99 SET options=-Wall -Wpedantic -std=c89 -ansi -pedantic
@echo on @echo on
%c_compiler% ../simple_playback.c -o ../bin/simple_playback.exe %options% %c_compiler% ../simple_playback.c -o ../bin/simple_playback.exe %options%
%c_compiler% ../simple_capture.c -o ../bin/simple_capture.exe %options% %c_compiler% ../simple_capture.c -o ../bin/simple_capture.exe %options%
%c_compiler% ../simple_enumeration.c -o ../bin/simple_enumeration.exe %options% %c_compiler% ../simple_enumeration.c -o ../bin/simple_enumeration.exe %options%
%c_compiler% ../simple_mixing.c -o ../bin/simple_mixing.exe %options%
%c_compiler% ../simple_playback_emscripten.c -o ../bin/simple_playback_emscripten.exe %options%
%c_compiler% ../advanced_config.c -o ../bin/advanced_config.exe %options% %c_compiler% ../advanced_config.c -o ../bin/advanced_config.exe %options%
+16 -15
View File
@@ -1,4 +1,4 @@
// This example simply captures data from your default microphone until you press Enter. The output is saved to the file specified on the command line. /* This example simply captures data from your default microphone until you press Enter. The output is saved to the file specified on the command line. */
#define MINIAUDIO_IMPLEMENTATION #define MINIAUDIO_IMPLEMENTATION
#include "../miniaudio.h" #include "../miniaudio.h"
@@ -11,45 +11,46 @@
void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount) void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount)
{ {
(void)pOutput;
drwav* pWav = (drwav*)pDevice->pUserData; drwav* pWav = (drwav*)pDevice->pUserData;
ma_assert(pWav != NULL); ma_assert(pWav != NULL);
drwav_write_pcm_frames(pWav, frameCount, pInput); drwav_write_pcm_frames(pWav, frameCount, pInput);
(void)pOutput;
} }
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
ma_result result;
drwav_data_format wavFormat;
drwav wav;
ma_device_config deviceConfig;
ma_device device;
if (argc < 2) { if (argc < 2) {
printf("No input file.\n"); printf("No input file.\n");
return -1; return -1;
} }
ma_result result;
drwav_data_format wavFormat;
wavFormat.container = drwav_container_riff; wavFormat.container = drwav_container_riff;
wavFormat.format = DR_WAVE_FORMAT_IEEE_FLOAT; wavFormat.format = DR_WAVE_FORMAT_IEEE_FLOAT;
wavFormat.channels = 2; wavFormat.channels = 2;
wavFormat.sampleRate = 44100; wavFormat.sampleRate = 44100;
wavFormat.bitsPerSample = 32; wavFormat.bitsPerSample = 32;
drwav wav;
if (drwav_init_file_write(&wav, argv[1], &wavFormat) == DRWAV_FALSE) { if (drwav_init_file_write(&wav, argv[1], &wavFormat) == DRWAV_FALSE) {
printf("Failed to initialize output file.\n"); printf("Failed to initialize output file.\n");
return -1; return -1;
} }
ma_device_config config = ma_device_config_init(ma_device_type_capture); deviceConfig = ma_device_config_init(ma_device_type_capture);
config.capture.format = ma_format_f32; deviceConfig.capture.format = ma_format_f32;
config.capture.channels = wavFormat.channels; deviceConfig.capture.channels = wavFormat.channels;
config.sampleRate = wavFormat.sampleRate; deviceConfig.sampleRate = wavFormat.sampleRate;
config.dataCallback = data_callback; deviceConfig.dataCallback = data_callback;
config.pUserData = &wav; deviceConfig.pUserData = &wav;
ma_device device; result = ma_device_init(NULL, &deviceConfig, &device);
result = ma_device_init(NULL, &config, &device);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
printf("Failed to initialize capture device.\n"); printf("Failed to initialize capture device.\n");
return -2; return -2;
+13 -10
View File
@@ -5,38 +5,41 @@
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
(void)argc; ma_result result;
(void)argv;
ma_context context; ma_context context;
ma_device_info* pPlaybackDeviceInfos;
ma_uint32 playbackDeviceCount;
ma_device_info* pCaptureDeviceInfos;
ma_uint32 captureDeviceCount;
ma_uint32 iDevice;
if (ma_context_init(NULL, 0, NULL, &context) != MA_SUCCESS) { if (ma_context_init(NULL, 0, NULL, &context) != MA_SUCCESS) {
printf("Failed to initialize context.\n"); printf("Failed to initialize context.\n");
return -2; return -2;
} }
ma_device_info* pPlaybackDeviceInfos; result = ma_context_get_devices(&context, &pPlaybackDeviceInfos, &playbackDeviceCount, &pCaptureDeviceInfos, &captureDeviceCount);
ma_uint32 playbackDeviceCount;
ma_device_info* pCaptureDeviceInfos;
ma_uint32 captureDeviceCount;
ma_result result = ma_context_get_devices(&context, &pPlaybackDeviceInfos, &playbackDeviceCount, &pCaptureDeviceInfos, &captureDeviceCount);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
printf("Failed to retrieve device information.\n"); printf("Failed to retrieve device information.\n");
return -3; return -3;
} }
printf("Playback Devices\n"); printf("Playback Devices\n");
for (ma_uint32 iDevice = 0; iDevice < playbackDeviceCount; ++iDevice) { for (iDevice = 0; iDevice < playbackDeviceCount; ++iDevice) {
printf(" %u: %s\n", iDevice, pPlaybackDeviceInfos[iDevice].name); printf(" %u: %s\n", iDevice, pPlaybackDeviceInfos[iDevice].name);
} }
printf("\n"); printf("\n");
printf("Capture Devices\n"); printf("Capture Devices\n");
for (ma_uint32 iDevice = 0; iDevice < captureDeviceCount; ++iDevice) { for (iDevice = 0; iDevice < captureDeviceCount; ++iDevice) {
printf(" %u: %s\n", iDevice, pCaptureDeviceInfos[iDevice].name); printf(" %u: %s\n", iDevice, pCaptureDeviceInfos[iDevice].name);
} }
ma_context_uninit(&context); ma_context_uninit(&context);
(void)argc;
(void)argv;
return 0; return 0;
} }
+25 -19
View File
@@ -4,11 +4,11 @@ Example: simple_mixing file1.wav file2.flac
*/ */
#define DR_FLAC_IMPLEMENTATION #define DR_FLAC_IMPLEMENTATION
#include "../extras/dr_flac.h" // Enables FLAC decoding. #include "../extras/dr_flac.h" /* Enables FLAC decoding. */
#define DR_MP3_IMPLEMENTATION #define DR_MP3_IMPLEMENTATION
#include "../extras/dr_mp3.h" // Enables MP3 decoding. #include "../extras/dr_mp3.h" /* Enables MP3 decoding. */
#define DR_WAV_IMPLEMENTATION #define DR_WAV_IMPLEMENTATION
#include "../extras/dr_wav.h" // Enables WAV decoding. #include "../extras/dr_wav.h" /* Enables WAV decoding. */
#define MINIAUDIO_IMPLEMENTATION #define MINIAUDIO_IMPLEMENTATION
#include "../miniaudio.h" #include "../miniaudio.h"
@@ -30,7 +30,8 @@ ma_event g_stopEvent; /* <-- Signaled by the audio thread, waited on by the main
ma_bool32 are_all_decoders_at_end() ma_bool32 are_all_decoders_at_end()
{ {
for (ma_uint32 iDecoder = 0; iDecoder < g_decoderCount; ++iDecoder) { ma_uint32 iDecoder;
for (iDecoder = 0; iDecoder < g_decoderCount; ++iDecoder) {
if (g_pDecodersAtEnd[iDecoder] == MA_FALSE) { if (g_pDecodersAtEnd[iDecoder] == MA_FALSE) {
return MA_FALSE; return MA_FALSE;
} }
@@ -51,6 +52,7 @@ ma_uint32 read_and_mix_pcm_frames_f32(ma_decoder* pDecoder, float* pOutputF32, m
ma_uint32 totalFramesRead = 0; ma_uint32 totalFramesRead = 0;
while (totalFramesRead < frameCount) { while (totalFramesRead < frameCount) {
ma_uint32 iSample;
ma_uint32 framesReadThisIteration; ma_uint32 framesReadThisIteration;
ma_uint32 totalFramesRemaining = frameCount - totalFramesRead; ma_uint32 totalFramesRemaining = frameCount - totalFramesRead;
ma_uint32 framesToReadThisIteration = tempCapInFrames; ma_uint32 framesToReadThisIteration = tempCapInFrames;
@@ -64,7 +66,7 @@ ma_uint32 read_and_mix_pcm_frames_f32(ma_decoder* pDecoder, float* pOutputF32, m
} }
/* Mix the frames together. */ /* Mix the frames together. */
for (ma_uint32 iSample = 0; iSample < framesReadThisIteration*CHANNEL_COUNT; ++iSample) { for (iSample = 0; iSample < framesReadThisIteration*CHANNEL_COUNT; ++iSample) {
pOutputF32[totalFramesRead*CHANNEL_COUNT + iSample] += temp[iSample]; pOutputF32[totalFramesRead*CHANNEL_COUNT + iSample] += temp[iSample];
} }
@@ -81,10 +83,11 @@ ma_uint32 read_and_mix_pcm_frames_f32(ma_decoder* pDecoder, float* pOutputF32, m
void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount) void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount)
{ {
float* pOutputF32 = (float*)pOutput; float* pOutputF32 = (float*)pOutput;
ma_uint32 iDecoder;
ma_assert(pDevice->playback.format == SAMPLE_FORMAT); /* <-- Important for this example. */ ma_assert(pDevice->playback.format == SAMPLE_FORMAT); /* <-- Important for this example. */
for (ma_uint32 iDecoder = 0; iDecoder < g_decoderCount; ++iDecoder) { for (iDecoder = 0; iDecoder < g_decoderCount; ++iDecoder) {
if (!g_pDecodersAtEnd[iDecoder]) { if (!g_pDecodersAtEnd[iDecoder]) {
ma_uint32 framesRead = read_and_mix_pcm_frames_f32(&g_pDecoders[iDecoder], pOutputF32, frameCount); ma_uint32 framesRead = read_and_mix_pcm_frames_f32(&g_pDecoders[iDecoder], pOutputF32, frameCount);
if (framesRead < frameCount) { if (framesRead < frameCount) {
@@ -108,6 +111,9 @@ int main(int argc, char** argv)
{ {
ma_result result; ma_result result;
ma_decoder_config decoderConfig; ma_decoder_config decoderConfig;
ma_device_config deviceConfig;
ma_device device;
ma_uint32 iDecoder;
if (argc < 2) { if (argc < 2) {
printf("No input files.\n"); printf("No input files.\n");
@@ -120,10 +126,11 @@ int main(int argc, char** argv)
/* In this example, all decoders need to have the same output format. */ /* In this example, all decoders need to have the same output format. */
decoderConfig = ma_decoder_config_init(SAMPLE_FORMAT, CHANNEL_COUNT, SAMPLE_RATE); decoderConfig = ma_decoder_config_init(SAMPLE_FORMAT, CHANNEL_COUNT, SAMPLE_RATE);
for (ma_uint32 iDecoder = 0; iDecoder < g_decoderCount; ++iDecoder) { for (iDecoder = 0; iDecoder < g_decoderCount; ++iDecoder) {
result = ma_decoder_init_file(argv[1+iDecoder], &decoderConfig, &g_pDecoders[iDecoder]); result = ma_decoder_init_file(argv[1+iDecoder], &decoderConfig, &g_pDecoders[iDecoder]);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
for (ma_uint32 iDecoder2 = 0; iDecoder2 < iDecoder; ++iDecoder2) { ma_uint32 iDecoder2;
for (iDecoder2 = 0; iDecoder2 < iDecoder; ++iDecoder2) {
ma_decoder_uninit(&g_pDecoders[iDecoder2]); ma_decoder_uninit(&g_pDecoders[iDecoder2]);
} }
free(g_pDecoders); free(g_pDecoders);
@@ -136,16 +143,15 @@ int main(int argc, char** argv)
} }
/* Create only a single device. The decoders will be mixed together in the callback. In this example the data format needs to be the same as the decoders. */ /* Create only a single device. The decoders will be mixed together in the callback. In this example the data format needs to be the same as the decoders. */
ma_device_config config = ma_device_config_init(ma_device_type_playback); deviceConfig = ma_device_config_init(ma_device_type_playback);
config.playback.format = SAMPLE_FORMAT; deviceConfig.playback.format = SAMPLE_FORMAT;
config.playback.channels = CHANNEL_COUNT; deviceConfig.playback.channels = CHANNEL_COUNT;
config.sampleRate = SAMPLE_RATE; deviceConfig.sampleRate = SAMPLE_RATE;
config.dataCallback = data_callback; deviceConfig.dataCallback = data_callback;
config.pUserData = NULL; deviceConfig.pUserData = NULL;
ma_device device; if (ma_device_init(NULL, &deviceConfig, &device) != MA_SUCCESS) {
if (ma_device_init(NULL, &config, &device) != MA_SUCCESS) { for (iDecoder = 0; iDecoder < g_decoderCount; ++iDecoder) {
for (ma_uint32 iDecoder = 0; iDecoder < g_decoderCount; ++iDecoder) {
ma_decoder_uninit(&g_pDecoders[iDecoder]); ma_decoder_uninit(&g_pDecoders[iDecoder]);
} }
free(g_pDecoders); free(g_pDecoders);
@@ -165,7 +171,7 @@ int main(int argc, char** argv)
/* Now we start playback and wait for the audio thread to tell us to stop. */ /* Now we start playback and wait for the audio thread to tell us to stop. */
if (ma_device_start(&device) != MA_SUCCESS) { if (ma_device_start(&device) != MA_SUCCESS) {
ma_device_uninit(&device); ma_device_uninit(&device);
for (ma_uint32 iDecoder = 0; iDecoder < g_decoderCount; ++iDecoder) { for (iDecoder = 0; iDecoder < g_decoderCount; ++iDecoder) {
ma_decoder_uninit(&g_pDecoders[iDecoder]); ma_decoder_uninit(&g_pDecoders[iDecoder]);
} }
free(g_pDecoders); free(g_pDecoders);
@@ -181,7 +187,7 @@ int main(int argc, char** argv)
/* Getting here means the audio thread has signaled that the device should be stopped. */ /* Getting here means the audio thread has signaled that the device should be stopped. */
ma_device_uninit(&device); ma_device_uninit(&device);
for (ma_uint32 iDecoder = 0; iDecoder < g_decoderCount; ++iDecoder) { for (iDecoder = 0; iDecoder < g_decoderCount; ++iDecoder) {
ma_decoder_uninit(&g_pDecoders[iDecoder]); ma_decoder_uninit(&g_pDecoders[iDecoder]);
} }
free(g_pDecoders); free(g_pDecoders);
+8 -8
View File
@@ -26,7 +26,7 @@ int main(int argc, char** argv)
{ {
ma_result result; ma_result result;
ma_decoder decoder; ma_decoder decoder;
ma_device_config config; ma_device_config deviceConfig;
ma_device device; ma_device device;
if (argc < 2) { if (argc < 2) {
@@ -39,14 +39,14 @@ int main(int argc, char** argv)
return -2; return -2;
} }
config = ma_device_config_init(ma_device_type_playback); deviceConfig = ma_device_config_init(ma_device_type_playback);
config.playback.format = decoder.outputFormat; deviceConfig.playback.format = decoder.outputFormat;
config.playback.channels = decoder.outputChannels; deviceConfig.playback.channels = decoder.outputChannels;
config.sampleRate = decoder.outputSampleRate; deviceConfig.sampleRate = decoder.outputSampleRate;
config.dataCallback = data_callback; deviceConfig.dataCallback = data_callback;
config.pUserData = &decoder; deviceConfig.pUserData = &decoder;
if (ma_device_init(NULL, &config, &device) != MA_SUCCESS) { if (ma_device_init(NULL, &deviceConfig, &device) != MA_SUCCESS) {
printf("Failed to open playback device.\n"); printf("Failed to open playback device.\n");
ma_decoder_uninit(&decoder); ma_decoder_uninit(&decoder);
return -3; return -3;
+17 -13
View File
@@ -17,32 +17,34 @@ void main_loop__em()
void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount) void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount)
{ {
(void)pInput; /* Unused. */ ma_sine_wave* pSineWave;
ma_assert(pDevice->playback.channels == DEVICE_CHANNELS); ma_assert(pDevice->playback.channels == DEVICE_CHANNELS);
ma_sine_wave* pSineWave = (ma_sine_wave*)pDevice->pUserData; pSineWave = (ma_sine_wave*)pDevice->pUserData;
ma_assert(pSineWave != NULL); ma_assert(pSineWave != NULL);
ma_sine_wave_read_f32(pSineWave, frameCount, (float*)pOutput); ma_sine_wave_read_f32(pSineWave, frameCount, (float*)pOutput);
(void)pInput; /* Unused. */
} }
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
(void)argc;
(void)argv;
ma_sine_wave sineWave; ma_sine_wave sineWave;
ma_device_config deviceConfig;
ma_device device;
ma_sine_wave_init(0.2, 400, DEVICE_SAMPLE_RATE, &sineWave); ma_sine_wave_init(0.2, 400, DEVICE_SAMPLE_RATE, &sineWave);
ma_device_config config = ma_device_config_init(ma_device_type_playback); deviceConfig = ma_device_config_init(ma_device_type_playback);
config.playback.format = DEVICE_FORMAT; deviceConfig.playback.format = DEVICE_FORMAT;
config.playback.channels = DEVICE_CHANNELS; deviceConfig.playback.channels = DEVICE_CHANNELS;
config.sampleRate = DEVICE_SAMPLE_RATE; deviceConfig.sampleRate = DEVICE_SAMPLE_RATE;
config.dataCallback = data_callback; deviceConfig.dataCallback = data_callback;
config.pUserData = &sineWave; deviceConfig.pUserData = &sineWave;
ma_device device; if (ma_device_init(NULL, &deviceConfig, &device) != MA_SUCCESS) {
if (ma_device_init(NULL, &config, &device) != MA_SUCCESS) {
printf("Failed to open playback device.\n"); printf("Failed to open playback device.\n");
return -4; return -4;
} }
@@ -64,5 +66,7 @@ int main(int argc, char** argv)
ma_device_uninit(&device); ma_device_uninit(&device);
(void)argc;
(void)argv;
return 0; return 0;
} }