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:
+122
-94
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
@@ -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;
|
||||||
|
|||||||
@@ -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
@@ -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);
|
||||||
|
|||||||
@@ -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,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;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user