mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-22 00:06:59 +02:00
Update examples to C89.
This commit is contained in:
+126
-98
@@ -16,7 +16,7 @@ void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uin
|
||||
(void)pOutput;
|
||||
(void)pInput;
|
||||
(void)frameCount;
|
||||
return; // Just output silence for this example.
|
||||
return; /* Just output silence for this example. */
|
||||
}
|
||||
|
||||
void stop_callback(ma_device* pDevice)
|
||||
@@ -27,63 +27,24 @@ void stop_callback(ma_device* pDevice)
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
ma_result result;
|
||||
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
|
||||
// common configuration settings, but you can set other members for more detailed control.
|
||||
ma_context_config 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;
|
||||
|
||||
|
||||
|
||||
// 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.
|
||||
/*
|
||||
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_wasapi, // Higest priority.
|
||||
ma_backend_wasapi, /* Higest priority. */
|
||||
ma_backend_dsound,
|
||||
ma_backend_winmm,
|
||||
ma_backend_coreaudio,
|
||||
@@ -96,92 +57,156 @@ int main(int argc, char** argv)
|
||||
ma_backend_aaudio,
|
||||
ma_backend_opensl,
|
||||
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) {
|
||||
printf("Failed to initialize context.");
|
||||
return -2;
|
||||
}
|
||||
|
||||
|
||||
// Enumerate devices.
|
||||
ma_device_info* pPlaybackDeviceInfos;
|
||||
ma_uint32 playbackDeviceCount;
|
||||
ma_device_info* pCaptureDeviceInfos;
|
||||
ma_uint32 captureDeviceCount;
|
||||
ma_result result = ma_context_get_devices(&context, &pPlaybackDeviceInfos, &playbackDeviceCount, &pCaptureDeviceInfos, &captureDeviceCount);
|
||||
/* Enumerate devices. */
|
||||
result = ma_context_get_devices(&context, &pPlaybackDeviceInfos, &playbackDeviceCount, &pCaptureDeviceInfos, &captureDeviceCount);
|
||||
if (result != MA_SUCCESS) {
|
||||
printf("Failed to retrieve device information.\n");
|
||||
return -3;
|
||||
}
|
||||
|
||||
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("\n");
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
// 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().
|
||||
//
|
||||
// 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.
|
||||
ma_device_config deviceConfig = ma_device_config_init(ma_device_type_playback);
|
||||
/*
|
||||
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().
|
||||
|
||||
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.
|
||||
*/
|
||||
deviceConfig = ma_device_config_init(ma_device_type_playback);
|
||||
deviceConfig.playback.format = ma_format_s16;
|
||||
deviceConfig.playback.channels = 2;
|
||||
deviceConfig.sampleRate = 48000;
|
||||
deviceConfig.dataCallback = data_callback;
|
||||
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;
|
||||
|
||||
// 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;
|
||||
|
||||
// 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
|
||||
// like the following:
|
||||
/*
|
||||
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
|
||||
like the following:
|
||||
*/
|
||||
deviceConfig.playback.channelMap[0] = MA_CHANNEL_FRONT_RIGHT;
|
||||
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
|
||||
// internally and is thus, theoretically, more efficient. In testing, however, this has been less stable than
|
||||
// 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!
|
||||
/*
|
||||
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
|
||||
internally and is thus, theoretically, more efficient. In testing, however, this has been less stable than
|
||||
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;
|
||||
|
||||
// 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
|
||||
// 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.
|
||||
/*
|
||||
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
|
||||
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
|
||||
ma_device_id customDeviceID;
|
||||
if (context.backend == ma_backend_alsa) {
|
||||
strcpy(customDeviceID.alsa, "hw:0,0");
|
||||
{
|
||||
ma_device_id customDeviceID;
|
||||
if (context.backend == ma_backend_alsa) {
|
||||
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
|
||||
// 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");
|
||||
/*
|
||||
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
|
||||
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");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
ma_device playbackDevice;
|
||||
if (ma_device_init(&context, &deviceConfig, &playbackDevice) != MA_SUCCESS) {
|
||||
printf("Failed to initialize playback device.\n");
|
||||
ma_context_uninit(&context);
|
||||
@@ -202,5 +227,8 @@ int main(int argc, char** argv)
|
||||
|
||||
|
||||
ma_context_uninit(&context);
|
||||
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user