mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-22 00:06:59 +02:00
Add syntax highlighting to documentation.
This commit is contained in:
@@ -262,58 +262,58 @@ around as user data for the device (device.pUserData).
|
||||
This example only works for output devices, but can be implemented for input devices by simply swapping the direction
|
||||
of data movement.</p>
|
||||
<div style="font-family:monospace; border:solid 1px #003800; border-left:solid 0.5em #003800; margin:1em 0em;"><pre style="margin:0.5em 1em; padding:0; line-height:125%">
|
||||
#define MINIAUDIO_IMPLEMENTATION
|
||||
#include "../miniaudio.h"
|
||||
<span style="color:#666666">#define</span> MINIAUDIO_IMPLEMENTATION
|
||||
<span style="color:#666666">#include</span> <span style="color:#cc3300">"../miniaudio.h"</span>
|
||||
|
||||
#include <stdio.h>
|
||||
<span style="color:#666666">#include</span> <span style="color:#cc3300"><stdio.h></span>
|
||||
|
||||
#define DEVICE_FORMAT ma_format_f32
|
||||
#define DEVICE_CHANNELS 1
|
||||
#define DEVICE_SAMPLE_RATE 48000
|
||||
<span style="color:#666666">#define</span> DEVICE_FORMAT ma_format_f32
|
||||
<span style="color:#666666">#define</span> DEVICE_CHANNELS 1
|
||||
<span style="color:#666666">#define</span> DEVICE_SAMPLE_RATE 48000
|
||||
|
||||
#define PCM_FRAME_CHUNK_SIZE 1234 /* <-- Play around with this to control your fixed sized buffer. */
|
||||
<span style="color:#666666">#define</span> PCM_FRAME_CHUNK_SIZE 1234 <span style="color:#009900">/* <-- Play around with this to control your fixed sized buffer. */</span>
|
||||
|
||||
ma_waveform g_sineWave;
|
||||
ma_pcm_rb g_rb; /* The ring buffer. */
|
||||
<span style="color:#0099cc">ma_waveform</span> g_sineWave;
|
||||
<span style="color:#0099cc">ma_pcm_rb</span> g_rb; <span style="color:#009900">/* The ring buffer. */</span>
|
||||
|
||||
void data_callback_fixed(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount)
|
||||
<span style="color:#0033ff">void</span> data_callback_fixed(<span style="color:#0099cc">ma_device</span>* pDevice, <span style="color:#0033ff">void</span>* pOutput, <span style="color:#0033ff">const</span> <span style="color:#0033ff">void</span>* pInput, <span style="color:#0099cc">ma_uint32</span> frameCount)
|
||||
{
|
||||
/*
|
||||
<span style="color:#009900">/*
|
||||
This callback will have a guaranteed and consistent size for frameCount. In this example we just fill the output buffer with a sine wave. This
|
||||
is where you would handle the callback just like normal, only now you can assume frameCount is a fixed size.
|
||||
*/
|
||||
printf("frameCount=%d\n", frameCount);
|
||||
*/</span>
|
||||
printf(<span style="color:#cc3300">"frameCount=%d\n"</span>, frameCount);
|
||||
|
||||
ma_waveform_read_pcm_frames(&g_sineWave, pOutput, frameCount);
|
||||
|
||||
/* Unused in this example. */
|
||||
(void)pDevice;
|
||||
(void)pInput;
|
||||
<span style="color:#009900">/* Unused in this example. */</span>
|
||||
(<span style="color:#0033ff">void</span>)pDevice;
|
||||
(<span style="color:#0033ff">void</span>)pInput;
|
||||
}
|
||||
|
||||
void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount)
|
||||
<span style="color:#0033ff">void</span> data_callback(<span style="color:#0099cc">ma_device</span>* pDevice, <span style="color:#0033ff">void</span>* pOutput, <span style="color:#0033ff">const</span> <span style="color:#0033ff">void</span>* pInput, <span style="color:#0099cc">ma_uint32</span> frameCount)
|
||||
{
|
||||
/*
|
||||
<span style="color:#009900">/*
|
||||
This is the device's main data callback. This will handle all of the fixed sized buffer management for you and will call data_callback_fixed()
|
||||
for you. You should do all of your normal callback stuff in data_callback_fixed().
|
||||
*/
|
||||
ma_uint32 pcmFramesAvailableInRB;
|
||||
ma_uint32 pcmFramesProcessed = 0;
|
||||
ma_uint8* pRunningOutput = (ma_uint8*)pOutput;
|
||||
*/</span>
|
||||
<span style="color:#0099cc">ma_uint32</span> pcmFramesAvailableInRB;
|
||||
<span style="color:#0099cc">ma_uint32</span> pcmFramesProcessed = 0;
|
||||
<span style="color:#0099cc">ma_uint8</span>* pRunningOutput = (<span style="color:#0099cc">ma_uint8</span>*)pOutput;
|
||||
|
||||
MA_ASSERT(pDevice->playback.channels == DEVICE_CHANNELS);
|
||||
|
||||
/*
|
||||
<span style="color:#009900">/*
|
||||
The first thing to do is check if there's enough data available in the ring buffer. If so we can read from it. Otherwise we need to keep filling
|
||||
the ring buffer until there's enough, making sure we only fill the ring buffer in chunks of PCM_FRAME_CHUNK_SIZE.
|
||||
*/
|
||||
while (pcmFramesProcessed < frameCount) { /* Keep going until we've filled the output buffer. */
|
||||
ma_uint32 framesRemaining = frameCount - pcmFramesProcessed;
|
||||
*/</span>
|
||||
<span style="color:#0033ff">while</span> (pcmFramesProcessed < frameCount) { <span style="color:#009900">/* Keep going until we've filled the output buffer. */</span>
|
||||
<span style="color:#0099cc">ma_uint32</span> framesRemaining = frameCount - pcmFramesProcessed;
|
||||
|
||||
pcmFramesAvailableInRB = ma_pcm_rb_available_read(&g_rb);
|
||||
if (pcmFramesAvailableInRB > 0) {
|
||||
ma_uint32 framesToRead = (framesRemaining < pcmFramesAvailableInRB) ? framesRemaining : pcmFramesAvailableInRB;
|
||||
void* pReadBuffer;
|
||||
<span style="color:#0033ff">if</span> (pcmFramesAvailableInRB > 0) {
|
||||
<span style="color:#0099cc">ma_uint32</span> framesToRead = (framesRemaining < pcmFramesAvailableInRB) ? framesRemaining : pcmFramesAvailableInRB;
|
||||
<span style="color:#0033ff">void</span>* pReadBuffer;
|
||||
|
||||
ma_pcm_rb_acquire_read(&g_rb, &framesToRead, &pReadBuffer);
|
||||
{
|
||||
@@ -323,35 +323,35 @@ void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uin
|
||||
|
||||
pRunningOutput += framesToRead * ma_get_bytes_per_frame(pDevice->playback.format, pDevice->playback.channels);
|
||||
pcmFramesProcessed += framesToRead;
|
||||
} else {
|
||||
/*
|
||||
} <span style="color:#0033ff">else</span> {
|
||||
<span style="color:#009900">/*
|
||||
There's nothing in the buffer. Fill it with more data from the callback. We reset the buffer first so that the read and write pointers
|
||||
are reset back to the start so we can fill the ring buffer in chunks of PCM_FRAME_CHUNK_SIZE which is what we initialized it with. Note
|
||||
that this is not how you would want to do it in a multi-threaded environment. In this case you would want to seek the write pointer
|
||||
forward via the producer thread and the read pointer forward via the consumer thread (this thread).
|
||||
*/
|
||||
ma_uint32 framesToWrite = PCM_FRAME_CHUNK_SIZE;
|
||||
void* pWriteBuffer;
|
||||
*/</span>
|
||||
<span style="color:#0099cc">ma_uint32</span> framesToWrite = PCM_FRAME_CHUNK_SIZE;
|
||||
<span style="color:#0033ff">void</span>* pWriteBuffer;
|
||||
|
||||
ma_pcm_rb_reset(&g_rb);
|
||||
ma_pcm_rb_acquire_write(&g_rb, &framesToWrite, &pWriteBuffer);
|
||||
{
|
||||
MA_ASSERT(framesToWrite == PCM_FRAME_CHUNK_SIZE); /* <-- This should always work in this example because we just reset the ring buffer. */
|
||||
MA_ASSERT(framesToWrite == PCM_FRAME_CHUNK_SIZE); <span style="color:#009900">/* <-- This should always work in this example because we just reset the ring buffer. */</span>
|
||||
data_callback_fixed(pDevice, pWriteBuffer, NULL, framesToWrite);
|
||||
}
|
||||
ma_pcm_rb_commit_write(&g_rb, framesToWrite, pWriteBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
/* Unused in this example. */
|
||||
(void)pInput;
|
||||
<span style="color:#009900">/* Unused in this example. */</span>
|
||||
(<span style="color:#0033ff">void</span>)pInput;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
<span style="color:#0033ff">int</span> main(<span style="color:#0033ff">int</span> argc, <span style="color:#0033ff">char</span>** argv)
|
||||
{
|
||||
ma_waveform_config waveformConfig;
|
||||
ma_device_config deviceConfig;
|
||||
ma_device device;
|
||||
<span style="color:#0099cc">ma_waveform_config</span> waveformConfig;
|
||||
<span style="color:#0099cc">ma_device_config</span> deviceConfig;
|
||||
<span style="color:#0099cc">ma_device</span> device;
|
||||
|
||||
waveformConfig = ma_waveform_config_init(DEVICE_FORMAT, DEVICE_CHANNELS, DEVICE_SAMPLE_RATE, ma_waveform_type_sine, 0.1, 220);
|
||||
ma_waveform_init(&waveformConfig, &g_sineWave);
|
||||
@@ -363,32 +363,32 @@ int main(int argc, char** argv)
|
||||
deviceConfig.playback.channels = DEVICE_CHANNELS;
|
||||
deviceConfig.sampleRate = DEVICE_SAMPLE_RATE;
|
||||
deviceConfig.dataCallback = data_callback;
|
||||
deviceConfig.pUserData = NULL; /* <-- Set this to a pointer to the ring buffer if you don't want it in global scope. */
|
||||
deviceConfig.pUserData = NULL; <span style="color:#009900">/* <-- Set this to a pointer to the ring buffer if you don't want it in global scope. */</span>
|
||||
|
||||
if (ma_device_init(NULL, &deviceConfig, &device) != MA_SUCCESS) {
|
||||
printf("Failed to open playback device.\n");
|
||||
<span style="color:#0033ff">if</span> (ma_device_init(NULL, &deviceConfig, &device) != MA_SUCCESS) {
|
||||
printf(<span style="color:#cc3300">"Failed to open playback device.\n"</span>);
|
||||
ma_pcm_rb_uninit(&g_rb);
|
||||
return -4;
|
||||
<span style="color:#0033ff">return</span> -4;
|
||||
}
|
||||
|
||||
printf("Device Name: %s\n", device.playback.name);
|
||||
printf(<span style="color:#cc3300">"Device Name: %s\n"</span>, device.playback.name);
|
||||
|
||||
if (ma_device_start(&device) != MA_SUCCESS) {
|
||||
printf("Failed to start playback device.\n");
|
||||
<span style="color:#0033ff">if</span> (ma_device_start(&device) != MA_SUCCESS) {
|
||||
printf(<span style="color:#cc3300">"Failed to start playback device.\n"</span>);
|
||||
ma_pcm_rb_uninit(&g_rb);
|
||||
ma_device_uninit(&device);
|
||||
return -5;
|
||||
<span style="color:#0033ff">return</span> -5;
|
||||
}
|
||||
|
||||
printf("Press Enter to quit...\n");
|
||||
printf(<span style="color:#cc3300">"Press Enter to quit...\n"</span>);
|
||||
getchar();
|
||||
|
||||
ma_device_uninit(&device);
|
||||
ma_pcm_rb_uninit(&g_rb);
|
||||
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
return 0;
|
||||
(<span style="color:#0033ff">void</span>)argc;
|
||||
(<span style="color:#0033ff">void</span>)argv;
|
||||
<span style="color:#0033ff">return</span> 0;
|
||||
}
|
||||
</pre></div></td>
|
||||
</tr></table>
|
||||
|
||||
@@ -255,40 +255,40 @@ Capturing works in a very similar way to playback. The only difference is the di
|
||||
the application sending data to the device, the device will send data to the application. This example just writes the
|
||||
data received by the microphone straight to a WAV file.</p>
|
||||
<div style="font-family:monospace; border:solid 1px #003800; border-left:solid 0.5em #003800; margin:1em 0em;"><pre style="margin:0.5em 1em; padding:0; line-height:125%">
|
||||
#define MINIAUDIO_IMPLEMENTATION
|
||||
#include "../miniaudio.h"
|
||||
<span style="color:#666666">#define</span> MINIAUDIO_IMPLEMENTATION
|
||||
<span style="color:#666666">#include</span> <span style="color:#cc3300">"../miniaudio.h"</span>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
<span style="color:#666666">#include</span> <span style="color:#cc3300"><stdlib.h></span>
|
||||
<span style="color:#666666">#include</span> <span style="color:#cc3300"><stdio.h></span>
|
||||
|
||||
void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount)
|
||||
<span style="color:#0033ff">void</span> data_callback(<span style="color:#0099cc">ma_device</span>* pDevice, <span style="color:#0033ff">void</span>* pOutput, <span style="color:#0033ff">const</span> <span style="color:#0033ff">void</span>* pInput, <span style="color:#0099cc">ma_uint32</span> frameCount)
|
||||
{
|
||||
ma_encoder* pEncoder = (ma_encoder*)pDevice->pUserData;
|
||||
<span style="color:#0099cc">ma_encoder</span>* pEncoder = (<span style="color:#0099cc">ma_encoder</span>*)pDevice->pUserData;
|
||||
MA_ASSERT(pEncoder != NULL);
|
||||
|
||||
ma_encoder_write_pcm_frames(pEncoder, pInput, frameCount);
|
||||
|
||||
(void)pOutput;
|
||||
(<span style="color:#0033ff">void</span>)pOutput;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
<span style="color:#0033ff">int</span> main(<span style="color:#0033ff">int</span> argc, <span style="color:#0033ff">char</span>** argv)
|
||||
{
|
||||
ma_result result;
|
||||
ma_encoder_config encoderConfig;
|
||||
ma_encoder encoder;
|
||||
ma_device_config deviceConfig;
|
||||
ma_device device;
|
||||
<span style="color:#0099cc">ma_result</span> result;
|
||||
<span style="color:#0099cc">ma_encoder_config</span> encoderConfig;
|
||||
<span style="color:#0099cc">ma_encoder</span> encoder;
|
||||
<span style="color:#0099cc">ma_device_config</span> deviceConfig;
|
||||
<span style="color:#0099cc">ma_device</span> device;
|
||||
|
||||
if (argc < 2) {
|
||||
printf("No input file.\n");
|
||||
return -1;
|
||||
<span style="color:#0033ff">if</span> (argc < 2) {
|
||||
printf(<span style="color:#cc3300">"No input file.\n"</span>);
|
||||
<span style="color:#0033ff">return</span> -1;
|
||||
}
|
||||
|
||||
encoderConfig = ma_encoder_config_init(ma_resource_format_wav, ma_format_f32, 2, 44100);
|
||||
|
||||
if (ma_encoder_init_file(argv[1], &encoderConfig, &encoder) != MA_SUCCESS) {
|
||||
printf("Failed to initialize output file.\n");
|
||||
return -1;
|
||||
<span style="color:#0033ff">if</span> (ma_encoder_init_file(argv[1], &encoderConfig, &encoder) != MA_SUCCESS) {
|
||||
printf(<span style="color:#cc3300">"Failed to initialize output file.\n"</span>);
|
||||
<span style="color:#0033ff">return</span> -1;
|
||||
}
|
||||
|
||||
deviceConfig = ma_device_config_init(ma_device_type_capture);
|
||||
@@ -299,25 +299,25 @@ int main(int argc, char** argv)
|
||||
deviceConfig.pUserData = &encoder;
|
||||
|
||||
result = ma_device_init(NULL, &deviceConfig, &device);
|
||||
if (result != MA_SUCCESS) {
|
||||
printf("Failed to initialize capture device.\n");
|
||||
return -2;
|
||||
<span style="color:#0033ff">if</span> (result != MA_SUCCESS) {
|
||||
printf(<span style="color:#cc3300">"Failed to initialize capture device.\n"</span>);
|
||||
<span style="color:#0033ff">return</span> -2;
|
||||
}
|
||||
|
||||
result = ma_device_start(&device);
|
||||
if (result != MA_SUCCESS) {
|
||||
<span style="color:#0033ff">if</span> (result != MA_SUCCESS) {
|
||||
ma_device_uninit(&device);
|
||||
printf("Failed to start device.\n");
|
||||
return -3;
|
||||
printf(<span style="color:#cc3300">"Failed to start device.\n"</span>);
|
||||
<span style="color:#0033ff">return</span> -3;
|
||||
}
|
||||
|
||||
printf("Press Enter to stop recording...\n");
|
||||
printf(<span style="color:#cc3300">"Press Enter to stop recording...\n"</span>);
|
||||
getchar();
|
||||
|
||||
ma_device_uninit(&device);
|
||||
ma_encoder_uninit(&encoder);
|
||||
|
||||
return 0;
|
||||
<span style="color:#0033ff">return</span> 0;
|
||||
}
|
||||
</pre></div></td>
|
||||
</tr></table>
|
||||
|
||||
@@ -257,31 +257,31 @@ glitching which the backend may not be able to recover from. For this reason, mi
|
||||
sample rate for both capture and playback. If internally the native sample rates differ, miniaudio will perform the
|
||||
sample rate conversion for you automatically.</p>
|
||||
<div style="font-family:monospace; border:solid 1px #003800; border-left:solid 0.5em #003800; margin:1em 0em;"><pre style="margin:0.5em 1em; padding:0; line-height:125%">
|
||||
#define MINIAUDIO_IMPLEMENTATION
|
||||
#include "../miniaudio.h"
|
||||
<span style="color:#666666">#define</span> MINIAUDIO_IMPLEMENTATION
|
||||
<span style="color:#666666">#include</span> <span style="color:#cc3300">"../miniaudio.h"</span>
|
||||
|
||||
#include <stdio.h>
|
||||
<span style="color:#666666">#include</span> <span style="color:#cc3300"><stdio.h></span>
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
void main_loop__em()
|
||||
<span style="color:#666666">#ifdef</span> __EMSCRIPTEN__
|
||||
<span style="color:#0033ff">void</span> main_loop__em()
|
||||
{
|
||||
}
|
||||
#endif
|
||||
<span style="color:#666666">#endif</span>
|
||||
|
||||
void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount)
|
||||
<span style="color:#0033ff">void</span> data_callback(<span style="color:#0099cc">ma_device</span>* pDevice, <span style="color:#0033ff">void</span>* pOutput, <span style="color:#0033ff">const</span> <span style="color:#0033ff">void</span>* pInput, <span style="color:#0099cc">ma_uint32</span> frameCount)
|
||||
{
|
||||
MA_ASSERT(pDevice->capture.format == pDevice->playback.format);
|
||||
MA_ASSERT(pDevice->capture.channels == pDevice->playback.channels);
|
||||
|
||||
/* In this example the format and channel count are the same for both input and output which means we can just memcpy(). */
|
||||
<span style="color:#009900">/* In this example the format and channel count are the same for both input and output which means we can just memcpy(). */</span>
|
||||
MA_COPY_MEMORY(pOutput, pInput, frameCount * ma_get_bytes_per_frame(pDevice->capture.format, pDevice->capture.channels));
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
<span style="color:#0033ff">int</span> main(<span style="color:#0033ff">int</span> argc, <span style="color:#0033ff">char</span>** argv)
|
||||
{
|
||||
ma_result result;
|
||||
ma_device_config deviceConfig;
|
||||
ma_device device;
|
||||
<span style="color:#0099cc">ma_result</span> result;
|
||||
<span style="color:#0099cc">ma_device_config</span> deviceConfig;
|
||||
<span style="color:#0099cc">ma_device</span> device;
|
||||
|
||||
deviceConfig = ma_device_config_init(ma_device_type_duplex);
|
||||
deviceConfig.capture.pDeviceID = NULL;
|
||||
@@ -293,28 +293,28 @@ int main(int argc, char** argv)
|
||||
deviceConfig.playback.channels = 2;
|
||||
deviceConfig.dataCallback = data_callback;
|
||||
result = ma_device_init(NULL, &deviceConfig, &device);
|
||||
if (result != MA_SUCCESS) {
|
||||
return result;
|
||||
<span style="color:#0033ff">if</span> (result != MA_SUCCESS) {
|
||||
<span style="color:#0033ff">return</span> result;
|
||||
}
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
<span style="color:#666666">#ifdef</span> __EMSCRIPTEN__
|
||||
getchar();
|
||||
#endif
|
||||
<span style="color:#666666">#endif</span>
|
||||
|
||||
ma_device_start(&device);
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
<span style="color:#666666">#ifdef</span> __EMSCRIPTEN__
|
||||
emscripten_set_main_loop(main_loop__em, 0, 1);
|
||||
#else
|
||||
printf("Press Enter to quit...\n");
|
||||
<span style="color:#666666">#else</span>
|
||||
printf(<span style="color:#cc3300">"Press Enter to quit...\n"</span>);
|
||||
getchar();
|
||||
#endif
|
||||
<span style="color:#666666">#endif</span>
|
||||
|
||||
ma_device_uninit(&device);
|
||||
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
return 0;
|
||||
(<span style="color:#0033ff">void</span>)argc;
|
||||
(<span style="color:#0033ff">void</span>)argv;
|
||||
<span style="color:#0033ff">return</span> 0;
|
||||
}
|
||||
</pre></div></td>
|
||||
</tr></table>
|
||||
|
||||
@@ -254,50 +254,50 @@ context sits above a device. You can have many devices to one context.
|
||||
If you use device enumeration, you should explicitly specify the same context you used for enumeration in the call to
|
||||
<span style="font-family:monospace;">ma_device_init()</span> when you initialize your devices.</p>
|
||||
<div style="font-family:monospace; border:solid 1px #003800; border-left:solid 0.5em #003800; margin:1em 0em;"><pre style="margin:0.5em 1em; padding:0; line-height:125%">
|
||||
#define MINIAUDIO_IMPLEMENTATION
|
||||
#include "../miniaudio.h"
|
||||
<span style="color:#666666">#define</span> MINIAUDIO_IMPLEMENTATION
|
||||
<span style="color:#666666">#include</span> <span style="color:#cc3300">"../miniaudio.h"</span>
|
||||
|
||||
#include <stdio.h>
|
||||
<span style="color:#666666">#include</span> <span style="color:#cc3300"><stdio.h></span>
|
||||
|
||||
int main(int argc, char** argv)
|
||||
<span style="color:#0033ff">int</span> main(<span style="color:#0033ff">int</span> argc, <span style="color:#0033ff">char</span>** argv)
|
||||
{
|
||||
ma_result result;
|
||||
ma_context context;
|
||||
ma_device_info* pPlaybackDeviceInfos;
|
||||
ma_uint32 playbackDeviceCount;
|
||||
ma_device_info* pCaptureDeviceInfos;
|
||||
ma_uint32 captureDeviceCount;
|
||||
ma_uint32 iDevice;
|
||||
<span style="color:#0099cc">ma_result</span> result;
|
||||
<span style="color:#0099cc">ma_context</span> context;
|
||||
<span style="color:#0099cc">ma_device_info</span>* pPlaybackDeviceInfos;
|
||||
<span style="color:#0099cc">ma_uint32</span> playbackDeviceCount;
|
||||
<span style="color:#0099cc">ma_device_info</span>* pCaptureDeviceInfos;
|
||||
<span style="color:#0099cc">ma_uint32</span> captureDeviceCount;
|
||||
<span style="color:#0099cc">ma_uint32</span> iDevice;
|
||||
|
||||
if (ma_context_init(NULL, 0, NULL, &context) != MA_SUCCESS) {
|
||||
printf("Failed to initialize context.\n");
|
||||
return -2;
|
||||
<span style="color:#0033ff">if</span> (ma_context_init(NULL, 0, NULL, &context) != MA_SUCCESS) {
|
||||
printf(<span style="color:#cc3300">"Failed to initialize context.\n"</span>);
|
||||
<span style="color:#0033ff">return</span> -2;
|
||||
}
|
||||
|
||||
result = ma_context_get_devices(&context, &pPlaybackDeviceInfos, &playbackDeviceCount, &pCaptureDeviceInfos, &captureDeviceCount);
|
||||
if (result != MA_SUCCESS) {
|
||||
printf("Failed to retrieve device information.\n");
|
||||
return -3;
|
||||
<span style="color:#0033ff">if</span> (result != MA_SUCCESS) {
|
||||
printf(<span style="color:#cc3300">"Failed to retrieve device information.\n"</span>);
|
||||
<span style="color:#0033ff">return</span> -3;
|
||||
}
|
||||
|
||||
printf("Playback Devices\n");
|
||||
for (iDevice = 0; iDevice < playbackDeviceCount; ++iDevice) {
|
||||
printf(" %u: %s\n", iDevice, pPlaybackDeviceInfos[iDevice].name);
|
||||
printf(<span style="color:#cc3300">"Playback Devices\n"</span>);
|
||||
<span style="color:#0033ff">for</span> (iDevice = 0; iDevice < playbackDeviceCount; ++iDevice) {
|
||||
printf(<span style="color:#cc3300">" %u: %s\n"</span>, iDevice, pPlaybackDeviceInfos[iDevice].name);
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
printf(<span style="color:#cc3300">"\n"</span>);
|
||||
|
||||
printf("Capture Devices\n");
|
||||
for (iDevice = 0; iDevice < captureDeviceCount; ++iDevice) {
|
||||
printf(" %u: %s\n", iDevice, pCaptureDeviceInfos[iDevice].name);
|
||||
printf(<span style="color:#cc3300">"Capture Devices\n"</span>);
|
||||
<span style="color:#0033ff">for</span> (iDevice = 0; iDevice < captureDeviceCount; ++iDevice) {
|
||||
printf(<span style="color:#cc3300">" %u: %s\n"</span>, iDevice, pCaptureDeviceInfos[iDevice].name);
|
||||
}
|
||||
|
||||
|
||||
ma_context_uninit(&context);
|
||||
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
return 0;
|
||||
(<span style="color:#0033ff">void</span>)argc;
|
||||
(<span style="color:#0033ff">void</span>)argv;
|
||||
<span style="color:#0033ff">return</span> 0;
|
||||
}
|
||||
</pre></div></td>
|
||||
</tr></table>
|
||||
|
||||
@@ -259,75 +259,75 @@ used indirectly with PulseAudio by choosing the appropriate loopback device afte
|
||||
To use loopback mode you just need to set the device type to ma_device_type_loopback and set the capture device config
|
||||
properties. The output buffer in the callback will be null whereas the input buffer will be valid.</p>
|
||||
<div style="font-family:monospace; border:solid 1px #003800; border-left:solid 0.5em #003800; margin:1em 0em;"><pre style="margin:0.5em 1em; padding:0; line-height:125%">
|
||||
#define MINIAUDIO_IMPLEMENTATION
|
||||
#include "../miniaudio.h"
|
||||
<span style="color:#666666">#define</span> MINIAUDIO_IMPLEMENTATION
|
||||
<span style="color:#666666">#include</span> <span style="color:#cc3300">"../miniaudio.h"</span>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
<span style="color:#666666">#include</span> <span style="color:#cc3300"><stdlib.h></span>
|
||||
<span style="color:#666666">#include</span> <span style="color:#cc3300"><stdio.h></span>
|
||||
|
||||
void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount)
|
||||
<span style="color:#0033ff">void</span> data_callback(<span style="color:#0099cc">ma_device</span>* pDevice, <span style="color:#0033ff">void</span>* pOutput, <span style="color:#0033ff">const</span> <span style="color:#0033ff">void</span>* pInput, <span style="color:#0099cc">ma_uint32</span> frameCount)
|
||||
{
|
||||
ma_encoder* pEncoder = (ma_encoder*)pDevice->pUserData;
|
||||
<span style="color:#0099cc">ma_encoder</span>* pEncoder = (<span style="color:#0099cc">ma_encoder</span>*)pDevice->pUserData;
|
||||
MA_ASSERT(pEncoder != NULL);
|
||||
|
||||
ma_encoder_write_pcm_frames(pEncoder, pInput, frameCount);
|
||||
|
||||
(void)pOutput;
|
||||
(<span style="color:#0033ff">void</span>)pOutput;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
<span style="color:#0033ff">int</span> main(<span style="color:#0033ff">int</span> argc, <span style="color:#0033ff">char</span>** argv)
|
||||
{
|
||||
ma_result result;
|
||||
ma_encoder_config encoderConfig;
|
||||
ma_encoder encoder;
|
||||
ma_device_config deviceConfig;
|
||||
ma_device device;
|
||||
<span style="color:#0099cc">ma_result</span> result;
|
||||
<span style="color:#0099cc">ma_encoder_config</span> encoderConfig;
|
||||
<span style="color:#0099cc">ma_encoder</span> encoder;
|
||||
<span style="color:#0099cc">ma_device_config</span> deviceConfig;
|
||||
<span style="color:#0099cc">ma_device</span> device;
|
||||
|
||||
/* Loopback mode is currently only supported on WASAPI. */
|
||||
<span style="color:#009900">/* Loopback mode is currently only supported on WASAPI. */</span>
|
||||
ma_backend backends[] = {
|
||||
ma_backend_wasapi
|
||||
};
|
||||
|
||||
if (argc < 2) {
|
||||
printf("No input file.\n");
|
||||
return -1;
|
||||
<span style="color:#0033ff">if</span> (argc < 2) {
|
||||
printf(<span style="color:#cc3300">"No input file.\n"</span>);
|
||||
<span style="color:#0033ff">return</span> -1;
|
||||
}
|
||||
|
||||
encoderConfig = ma_encoder_config_init(ma_resource_format_wav, ma_format_f32, 2, 44100);
|
||||
|
||||
if (ma_encoder_init_file(argv[1], &encoderConfig, &encoder) != MA_SUCCESS) {
|
||||
printf("Failed to initialize output file.\n");
|
||||
return -1;
|
||||
<span style="color:#0033ff">if</span> (ma_encoder_init_file(argv[1], &encoderConfig, &encoder) != MA_SUCCESS) {
|
||||
printf(<span style="color:#cc3300">"Failed to initialize output file.\n"</span>);
|
||||
<span style="color:#0033ff">return</span> -1;
|
||||
}
|
||||
|
||||
deviceConfig = ma_device_config_init(ma_device_type_loopback);
|
||||
deviceConfig.capture.pDeviceID = NULL; /* Use default device for this example. Set this to the ID of a _playback_ device if you want to capture from a specific device. */
|
||||
deviceConfig.capture.pDeviceID = NULL; <span style="color:#009900">/* Use default device for this example. Set this to the ID of a _playback_ device if you want to capture from a specific device. */</span>
|
||||
deviceConfig.capture.format = encoder.config.format;
|
||||
deviceConfig.capture.channels = encoder.config.channels;
|
||||
deviceConfig.sampleRate = encoder.config.sampleRate;
|
||||
deviceConfig.dataCallback = data_callback;
|
||||
deviceConfig.pUserData = &encoder;
|
||||
|
||||
result = ma_device_init_ex(backends, sizeof(backends)/sizeof(backends[0]), NULL, &deviceConfig, &device);
|
||||
if (result != MA_SUCCESS) {
|
||||
printf("Failed to initialize loopback device.\n");
|
||||
return -2;
|
||||
result = ma_device_init_ex(backends, <span style="color:#0033ff">sizeof</span>(backends)/<span style="color:#0033ff">sizeof</span>(backends[0]), NULL, &deviceConfig, &device);
|
||||
<span style="color:#0033ff">if</span> (result != MA_SUCCESS) {
|
||||
printf(<span style="color:#cc3300">"Failed to initialize loopback device.\n"</span>);
|
||||
<span style="color:#0033ff">return</span> -2;
|
||||
}
|
||||
|
||||
result = ma_device_start(&device);
|
||||
if (result != MA_SUCCESS) {
|
||||
<span style="color:#0033ff">if</span> (result != MA_SUCCESS) {
|
||||
ma_device_uninit(&device);
|
||||
printf("Failed to start device.\n");
|
||||
return -3;
|
||||
printf(<span style="color:#cc3300">"Failed to start device.\n"</span>);
|
||||
<span style="color:#0033ff">return</span> -3;
|
||||
}
|
||||
|
||||
printf("Press Enter to stop recording...\n");
|
||||
printf(<span style="color:#cc3300">"Press Enter to stop recording...\n"</span>);
|
||||
getchar();
|
||||
|
||||
ma_device_uninit(&device);
|
||||
ma_encoder_uninit(&encoder);
|
||||
|
||||
return 0;
|
||||
<span style="color:#0033ff">return</span> 0;
|
||||
}
|
||||
</pre></div></td>
|
||||
</tr></table>
|
||||
|
||||
@@ -250,44 +250,44 @@ This example uses a decoder as the data source. Decoders can be used with the <s
|
||||
supports looping via the <span style="font-family:monospace;">ma_data_source_read_pcm_frames()</span> API. To use it, all you need to do is pass a pointer to the
|
||||
decoder straight into <span style="font-family:monospace;">ma_data_source_read_pcm_frames()</span> and it will just work.</p>
|
||||
<div style="font-family:monospace; border:solid 1px #003800; border-left:solid 0.5em #003800; margin:1em 0em;"><pre style="margin:0.5em 1em; padding:0; line-height:125%">
|
||||
#define MINIAUDIO_IMPLEMENTATION
|
||||
#include "../miniaudio.h"
|
||||
<span style="color:#666666">#define</span> MINIAUDIO_IMPLEMENTATION
|
||||
<span style="color:#666666">#include</span> <span style="color:#cc3300">"../miniaudio.h"</span>
|
||||
|
||||
#include <stdio.h>
|
||||
<span style="color:#666666">#include</span> <span style="color:#cc3300"><stdio.h></span>
|
||||
|
||||
void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount)
|
||||
<span style="color:#0033ff">void</span> data_callback(<span style="color:#0099cc">ma_device</span>* pDevice, <span style="color:#0033ff">void</span>* pOutput, <span style="color:#0033ff">const</span> <span style="color:#0033ff">void</span>* pInput, <span style="color:#0099cc">ma_uint32</span> frameCount)
|
||||
{
|
||||
ma_bool32 isLooping = MA_TRUE;
|
||||
<span style="color:#0099cc">ma_bool32</span> isLooping = MA_TRUE;
|
||||
|
||||
ma_decoder* pDecoder = (ma_decoder*)pDevice->pUserData;
|
||||
if (pDecoder == NULL) {
|
||||
return;
|
||||
<span style="color:#0099cc">ma_decoder</span>* pDecoder = (<span style="color:#0099cc">ma_decoder</span>*)pDevice->pUserData;
|
||||
<span style="color:#0033ff">if</span> (pDecoder == NULL) {
|
||||
<span style="color:#0033ff">return</span>;
|
||||
}
|
||||
|
||||
/*
|
||||
<span style="color:#009900">/*
|
||||
A decoder is a data source which means you can seemlessly plug it into the ma_data_source API. We can therefore take advantage
|
||||
of the "loop" parameter of ma_data_source_read_pcm_frames() to handle looping for us.
|
||||
*/
|
||||
*/</span>
|
||||
ma_data_source_read_pcm_frames(pDecoder, pOutput, frameCount, NULL, isLooping);
|
||||
|
||||
(void)pInput;
|
||||
(<span style="color:#0033ff">void</span>)pInput;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
<span style="color:#0033ff">int</span> main(<span style="color:#0033ff">int</span> argc, <span style="color:#0033ff">char</span>** argv)
|
||||
{
|
||||
ma_result result;
|
||||
ma_decoder decoder;
|
||||
ma_device_config deviceConfig;
|
||||
ma_device device;
|
||||
<span style="color:#0099cc">ma_result</span> result;
|
||||
<span style="color:#0099cc">ma_decoder</span> decoder;
|
||||
<span style="color:#0099cc">ma_device_config</span> deviceConfig;
|
||||
<span style="color:#0099cc">ma_device</span> device;
|
||||
|
||||
if (argc < 2) {
|
||||
printf("No input file.\n");
|
||||
return -1;
|
||||
<span style="color:#0033ff">if</span> (argc < 2) {
|
||||
printf(<span style="color:#cc3300">"No input file.\n"</span>);
|
||||
<span style="color:#0033ff">return</span> -1;
|
||||
}
|
||||
|
||||
result = ma_decoder_init_file(argv[1], NULL, &decoder);
|
||||
if (result != MA_SUCCESS) {
|
||||
return -2;
|
||||
<span style="color:#0033ff">if</span> (result != MA_SUCCESS) {
|
||||
<span style="color:#0033ff">return</span> -2;
|
||||
}
|
||||
|
||||
deviceConfig = ma_device_config_init(ma_device_type_playback);
|
||||
@@ -297,26 +297,26 @@ int main(int argc, char** argv)
|
||||
deviceConfig.dataCallback = data_callback;
|
||||
deviceConfig.pUserData = &decoder;
|
||||
|
||||
if (ma_device_init(NULL, &deviceConfig, &device) != MA_SUCCESS) {
|
||||
printf("Failed to open playback device.\n");
|
||||
<span style="color:#0033ff">if</span> (ma_device_init(NULL, &deviceConfig, &device) != MA_SUCCESS) {
|
||||
printf(<span style="color:#cc3300">"Failed to open playback device.\n"</span>);
|
||||
ma_decoder_uninit(&decoder);
|
||||
return -3;
|
||||
<span style="color:#0033ff">return</span> -3;
|
||||
}
|
||||
|
||||
if (ma_device_start(&device) != MA_SUCCESS) {
|
||||
printf("Failed to start playback device.\n");
|
||||
<span style="color:#0033ff">if</span> (ma_device_start(&device) != MA_SUCCESS) {
|
||||
printf(<span style="color:#cc3300">"Failed to start playback device.\n"</span>);
|
||||
ma_device_uninit(&device);
|
||||
ma_decoder_uninit(&decoder);
|
||||
return -4;
|
||||
<span style="color:#0033ff">return</span> -4;
|
||||
}
|
||||
|
||||
printf("Press Enter to quit...");
|
||||
printf(<span style="color:#cc3300">"Press Enter to quit..."</span>);
|
||||
getchar();
|
||||
|
||||
ma_device_uninit(&device);
|
||||
ma_decoder_uninit(&decoder);
|
||||
|
||||
return 0;
|
||||
<span style="color:#0033ff">return</span> 0;
|
||||
}
|
||||
</pre></div></td>
|
||||
</tr></table>
|
||||
|
||||
@@ -258,139 +258,139 @@ is when sample are clampled to their minimum and maximum range, which for floati
|
||||
Usage: simple_mixing [input file 0] [input file 1] ... [input file n]
|
||||
Example: simple_mixing file1.wav file2.flac
|
||||
</pre></div><div style="font-family:monospace; border:solid 1px #003800; border-left:solid 0.5em #003800; margin:1em 0em;"><pre style="margin:0.5em 1em; padding:0; line-height:125%">
|
||||
#define MINIAUDIO_IMPLEMENTATION
|
||||
#include "../miniaudio.h"
|
||||
<span style="color:#666666">#define</span> MINIAUDIO_IMPLEMENTATION
|
||||
<span style="color:#666666">#include</span> <span style="color:#cc3300">"../miniaudio.h"</span>
|
||||
|
||||
#include <stdio.h>
|
||||
<span style="color:#666666">#include</span> <span style="color:#cc3300"><stdio.h></span>
|
||||
|
||||
/*
|
||||
<span style="color:#009900">/*
|
||||
For simplicity, this example requires the device to use floating point samples.
|
||||
*/
|
||||
#define SAMPLE_FORMAT ma_format_f32
|
||||
#define CHANNEL_COUNT 2
|
||||
#define SAMPLE_RATE 48000
|
||||
*/</span>
|
||||
<span style="color:#666666">#define</span> SAMPLE_FORMAT ma_format_f32
|
||||
<span style="color:#666666">#define</span> CHANNEL_COUNT 2
|
||||
<span style="color:#666666">#define</span> SAMPLE_RATE 48000
|
||||
|
||||
ma_uint32 g_decoderCount;
|
||||
ma_decoder* g_pDecoders;
|
||||
ma_bool32* g_pDecodersAtEnd;
|
||||
<span style="color:#0099cc">ma_uint32</span> g_decoderCount;
|
||||
<span style="color:#0099cc">ma_decoder</span>* g_pDecoders;
|
||||
<span style="color:#0099cc">ma_bool32</span>* g_pDecodersAtEnd;
|
||||
|
||||
ma_event g_stopEvent; /* <-- Signaled by the audio thread, waited on by the main thread. */
|
||||
<span style="color:#0099cc">ma_event</span> g_stopEvent; <span style="color:#009900">/* <-- Signaled by the audio thread, waited on by the main thread. */</span>
|
||||
|
||||
ma_bool32 are_all_decoders_at_end()
|
||||
<span style="color:#0099cc">ma_bool32</span> are_all_decoders_at_end()
|
||||
{
|
||||
ma_uint32 iDecoder;
|
||||
for (iDecoder = 0; iDecoder < g_decoderCount; ++iDecoder) {
|
||||
if (g_pDecodersAtEnd[iDecoder] == MA_FALSE) {
|
||||
return MA_FALSE;
|
||||
<span style="color:#0099cc">ma_uint32</span> iDecoder;
|
||||
<span style="color:#0033ff">for</span> (iDecoder = 0; iDecoder < g_decoderCount; ++iDecoder) {
|
||||
<span style="color:#0033ff">if</span> (g_pDecodersAtEnd[iDecoder] == MA_FALSE) {
|
||||
<span style="color:#0033ff">return</span> MA_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return MA_TRUE;
|
||||
<span style="color:#0033ff">return</span> MA_TRUE;
|
||||
}
|
||||
|
||||
ma_uint32 read_and_mix_pcm_frames_f32(ma_decoder* pDecoder, float* pOutputF32, ma_uint32 frameCount)
|
||||
<span style="color:#0099cc">ma_uint32</span> read_and_mix_pcm_frames_f32(<span style="color:#0099cc">ma_decoder</span>* pDecoder, <span style="color:#0033ff">float</span>* pOutputF32, <span style="color:#0099cc">ma_uint32</span> frameCount)
|
||||
{
|
||||
/*
|
||||
<span style="color:#009900">/*
|
||||
The way mixing works is that we just read into a temporary buffer, then take the contents of that buffer and mix it with the
|
||||
contents of the output buffer by simply adding the samples together. You could also clip the samples to -1..+1, but I'm not
|
||||
doing that in this example.
|
||||
*/
|
||||
float temp[4096];
|
||||
ma_uint32 tempCapInFrames = ma_countof(temp) / CHANNEL_COUNT;
|
||||
ma_uint32 totalFramesRead = 0;
|
||||
*/</span>
|
||||
<span style="color:#0033ff">float</span> temp[4096];
|
||||
<span style="color:#0099cc">ma_uint32</span> tempCapInFrames = ma_countof(temp) / CHANNEL_COUNT;
|
||||
<span style="color:#0099cc">ma_uint32</span> totalFramesRead = 0;
|
||||
|
||||
while (totalFramesRead < frameCount) {
|
||||
ma_uint32 iSample;
|
||||
ma_uint32 framesReadThisIteration;
|
||||
ma_uint32 totalFramesRemaining = frameCount - totalFramesRead;
|
||||
ma_uint32 framesToReadThisIteration = tempCapInFrames;
|
||||
if (framesToReadThisIteration > totalFramesRemaining) {
|
||||
<span style="color:#0033ff">while</span> (totalFramesRead < frameCount) {
|
||||
<span style="color:#0099cc">ma_uint32</span> iSample;
|
||||
<span style="color:#0099cc">ma_uint32</span> framesReadThisIteration;
|
||||
<span style="color:#0099cc">ma_uint32</span> totalFramesRemaining = frameCount - totalFramesRead;
|
||||
<span style="color:#0099cc">ma_uint32</span> framesToReadThisIteration = tempCapInFrames;
|
||||
<span style="color:#0033ff">if</span> (framesToReadThisIteration > totalFramesRemaining) {
|
||||
framesToReadThisIteration = totalFramesRemaining;
|
||||
}
|
||||
|
||||
framesReadThisIteration = (ma_uint32)ma_decoder_read_pcm_frames(pDecoder, temp, framesToReadThisIteration);
|
||||
if (framesReadThisIteration == 0) {
|
||||
break;
|
||||
framesReadThisIteration = (<span style="color:#0099cc">ma_uint32</span>)ma_decoder_read_pcm_frames(pDecoder, temp, framesToReadThisIteration);
|
||||
<span style="color:#0033ff">if</span> (framesReadThisIteration == 0) {
|
||||
<span style="color:#0033ff">break</span>;
|
||||
}
|
||||
|
||||
/* Mix the frames together. */
|
||||
for (iSample = 0; iSample < framesReadThisIteration*CHANNEL_COUNT; ++iSample) {
|
||||
<span style="color:#009900">/* Mix the frames together. */</span>
|
||||
<span style="color:#0033ff">for</span> (iSample = 0; iSample < framesReadThisIteration*CHANNEL_COUNT; ++iSample) {
|
||||
pOutputF32[totalFramesRead*CHANNEL_COUNT + iSample] += temp[iSample];
|
||||
}
|
||||
|
||||
totalFramesRead += framesReadThisIteration;
|
||||
|
||||
if (framesReadThisIteration < framesToReadThisIteration) {
|
||||
break; /* Reached EOF. */
|
||||
<span style="color:#0033ff">if</span> (framesReadThisIteration < framesToReadThisIteration) {
|
||||
<span style="color:#0033ff">break</span>; <span style="color:#009900">/* Reached EOF. */</span>
|
||||
}
|
||||
}
|
||||
|
||||
return totalFramesRead;
|
||||
<span style="color:#0033ff">return</span> totalFramesRead;
|
||||
}
|
||||
|
||||
void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount)
|
||||
<span style="color:#0033ff">void</span> data_callback(<span style="color:#0099cc">ma_device</span>* pDevice, <span style="color:#0033ff">void</span>* pOutput, <span style="color:#0033ff">const</span> <span style="color:#0033ff">void</span>* pInput, <span style="color:#0099cc">ma_uint32</span> frameCount)
|
||||
{
|
||||
float* pOutputF32 = (float*)pOutput;
|
||||
ma_uint32 iDecoder;
|
||||
<span style="color:#0033ff">float</span>* pOutputF32 = (<span style="color:#0033ff">float</span>*)pOutput;
|
||||
<span style="color:#0099cc">ma_uint32</span> iDecoder;
|
||||
|
||||
MA_ASSERT(pDevice->playback.format == SAMPLE_FORMAT); /* <-- Important for this example. */
|
||||
MA_ASSERT(pDevice->playback.format == SAMPLE_FORMAT); <span style="color:#009900">/* <-- Important for this example. */</span>
|
||||
|
||||
for (iDecoder = 0; iDecoder < g_decoderCount; ++iDecoder) {
|
||||
if (!g_pDecodersAtEnd[iDecoder]) {
|
||||
ma_uint32 framesRead = read_and_mix_pcm_frames_f32(&g_pDecoders[iDecoder], pOutputF32, frameCount);
|
||||
if (framesRead < frameCount) {
|
||||
<span style="color:#0033ff">for</span> (iDecoder = 0; iDecoder < g_decoderCount; ++iDecoder) {
|
||||
<span style="color:#0033ff">if</span> (!g_pDecodersAtEnd[iDecoder]) {
|
||||
<span style="color:#0099cc">ma_uint32</span> framesRead = read_and_mix_pcm_frames_f32(&g_pDecoders[iDecoder], pOutputF32, frameCount);
|
||||
<span style="color:#0033ff">if</span> (framesRead < frameCount) {
|
||||
g_pDecodersAtEnd[iDecoder] = MA_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
<span style="color:#009900">/*
|
||||
If at the end all of our decoders are at the end we need to stop. We cannot stop the device in the callback. Instead we need to
|
||||
signal an event to indicate that it's stopped. The main thread will be waiting on the event, after which it will stop the device.
|
||||
*/
|
||||
if (are_all_decoders_at_end()) {
|
||||
*/</span>
|
||||
<span style="color:#0033ff">if</span> (are_all_decoders_at_end()) {
|
||||
ma_event_signal(&g_stopEvent);
|
||||
}
|
||||
|
||||
(void)pInput;
|
||||
(<span style="color:#0033ff">void</span>)pInput;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
<span style="color:#0033ff">int</span> main(<span style="color:#0033ff">int</span> argc, <span style="color:#0033ff">char</span>** argv)
|
||||
{
|
||||
ma_result result;
|
||||
ma_decoder_config decoderConfig;
|
||||
ma_device_config deviceConfig;
|
||||
ma_device device;
|
||||
ma_uint32 iDecoder;
|
||||
<span style="color:#0099cc">ma_result</span> result;
|
||||
<span style="color:#0099cc">ma_decoder_config</span> decoderConfig;
|
||||
<span style="color:#0099cc">ma_device_config</span> deviceConfig;
|
||||
<span style="color:#0099cc">ma_device</span> device;
|
||||
<span style="color:#0099cc">ma_uint32</span> iDecoder;
|
||||
|
||||
if (argc < 2) {
|
||||
printf("No input files.\n");
|
||||
return -1;
|
||||
<span style="color:#0033ff">if</span> (argc < 2) {
|
||||
printf(<span style="color:#cc3300">"No input files.\n"</span>);
|
||||
<span style="color:#0033ff">return</span> -1;
|
||||
}
|
||||
|
||||
g_decoderCount = argc-1;
|
||||
g_pDecoders = (ma_decoder*)malloc(sizeof(*g_pDecoders) * g_decoderCount);
|
||||
g_pDecodersAtEnd = (ma_bool32*) malloc(sizeof(*g_pDecodersAtEnd) * g_decoderCount);
|
||||
g_pDecoders = (<span style="color:#0099cc">ma_decoder</span>*)malloc(<span style="color:#0033ff">sizeof</span>(*g_pDecoders) * g_decoderCount);
|
||||
g_pDecodersAtEnd = (<span style="color:#0099cc">ma_bool32</span>*) malloc(<span style="color:#0033ff">sizeof</span>(*g_pDecodersAtEnd) * g_decoderCount);
|
||||
|
||||
/* In this example, all decoders need to have the same output format. */
|
||||
<span style="color:#009900">/* In this example, all decoders need to have the same output format. */</span>
|
||||
decoderConfig = ma_decoder_config_init(SAMPLE_FORMAT, CHANNEL_COUNT, SAMPLE_RATE);
|
||||
for (iDecoder = 0; iDecoder < g_decoderCount; ++iDecoder) {
|
||||
<span style="color:#0033ff">for</span> (iDecoder = 0; iDecoder < g_decoderCount; ++iDecoder) {
|
||||
result = ma_decoder_init_file(argv[1+iDecoder], &decoderConfig, &g_pDecoders[iDecoder]);
|
||||
if (result != MA_SUCCESS) {
|
||||
ma_uint32 iDecoder2;
|
||||
for (iDecoder2 = 0; iDecoder2 < iDecoder; ++iDecoder2) {
|
||||
<span style="color:#0033ff">if</span> (result != MA_SUCCESS) {
|
||||
<span style="color:#0099cc">ma_uint32</span> iDecoder2;
|
||||
<span style="color:#0033ff">for</span> (iDecoder2 = 0; iDecoder2 < iDecoder; ++iDecoder2) {
|
||||
ma_decoder_uninit(&g_pDecoders[iDecoder2]);
|
||||
}
|
||||
free(g_pDecoders);
|
||||
free(g_pDecodersAtEnd);
|
||||
|
||||
printf("Failed to load %s.\n", argv[1+iDecoder]);
|
||||
return -3;
|
||||
printf(<span style="color:#cc3300">"Failed to load %s.\n"</span>, argv[1+iDecoder]);
|
||||
<span style="color:#0033ff">return</span> -3;
|
||||
}
|
||||
g_pDecodersAtEnd[iDecoder] = MA_FALSE;
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
<span style="color:#009900">/* 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. */</span>
|
||||
deviceConfig = ma_device_config_init(ma_device_type_playback);
|
||||
deviceConfig.playback.format = SAMPLE_FORMAT;
|
||||
deviceConfig.playback.channels = CHANNEL_COUNT;
|
||||
@@ -398,50 +398,50 @@ int main(int argc, char** argv)
|
||||
deviceConfig.dataCallback = data_callback;
|
||||
deviceConfig.pUserData = NULL;
|
||||
|
||||
if (ma_device_init(NULL, &deviceConfig, &device) != MA_SUCCESS) {
|
||||
for (iDecoder = 0; iDecoder < g_decoderCount; ++iDecoder) {
|
||||
<span style="color:#0033ff">if</span> (ma_device_init(NULL, &deviceConfig, &device) != MA_SUCCESS) {
|
||||
<span style="color:#0033ff">for</span> (iDecoder = 0; iDecoder < g_decoderCount; ++iDecoder) {
|
||||
ma_decoder_uninit(&g_pDecoders[iDecoder]);
|
||||
}
|
||||
free(g_pDecoders);
|
||||
free(g_pDecodersAtEnd);
|
||||
|
||||
printf("Failed to open playback device.\n");
|
||||
return -3;
|
||||
printf(<span style="color:#cc3300">"Failed to open playback device.\n"</span>);
|
||||
<span style="color:#0033ff">return</span> -3;
|
||||
}
|
||||
|
||||
/*
|
||||
<span style="color:#009900">/*
|
||||
We can't stop in the audio thread so we instead need to use an event. We wait on this thread in the main thread, and signal it in the audio thread. This
|
||||
needs to be done before starting the device. We need a context to initialize the event, which we can get from the device. Alternatively you can initialize
|
||||
a context separately, but we don't need to do that for this example.
|
||||
*/
|
||||
*/</span>
|
||||
ma_event_init(&g_stopEvent);
|
||||
|
||||
/* Now we start playback and wait for the audio thread to tell us to stop. */
|
||||
if (ma_device_start(&device) != MA_SUCCESS) {
|
||||
<span style="color:#009900">/* Now we start playback and wait for the audio thread to tell us to stop. */</span>
|
||||
<span style="color:#0033ff">if</span> (ma_device_start(&device) != MA_SUCCESS) {
|
||||
ma_device_uninit(&device);
|
||||
for (iDecoder = 0; iDecoder < g_decoderCount; ++iDecoder) {
|
||||
<span style="color:#0033ff">for</span> (iDecoder = 0; iDecoder < g_decoderCount; ++iDecoder) {
|
||||
ma_decoder_uninit(&g_pDecoders[iDecoder]);
|
||||
}
|
||||
free(g_pDecoders);
|
||||
free(g_pDecodersAtEnd);
|
||||
|
||||
printf("Failed to start playback device.\n");
|
||||
return -4;
|
||||
printf(<span style="color:#cc3300">"Failed to start playback device.\n"</span>);
|
||||
<span style="color:#0033ff">return</span> -4;
|
||||
}
|
||||
|
||||
printf("Waiting for playback to complete...\n");
|
||||
printf(<span style="color:#cc3300">"Waiting for playback to complete...\n"</span>);
|
||||
ma_event_wait(&g_stopEvent);
|
||||
|
||||
/* Getting here means the audio thread has signaled that the device should be stopped. */
|
||||
<span style="color:#009900">/* Getting here means the audio thread has signaled that the device should be stopped. */</span>
|
||||
ma_device_uninit(&device);
|
||||
|
||||
for (iDecoder = 0; iDecoder < g_decoderCount; ++iDecoder) {
|
||||
<span style="color:#0033ff">for</span> (iDecoder = 0; iDecoder < g_decoderCount; ++iDecoder) {
|
||||
ma_decoder_uninit(&g_pDecoders[iDecoder]);
|
||||
}
|
||||
free(g_pDecoders);
|
||||
free(g_pDecodersAtEnd);
|
||||
|
||||
return 0;
|
||||
<span style="color:#0033ff">return</span> 0;
|
||||
}
|
||||
</pre></div></td>
|
||||
</tr></table>
|
||||
|
||||
@@ -257,38 +257,38 @@ device and can be used independently of it. This example only plays back a singl
|
||||
back multiple files by simple loading multiple decoders and mixing them (do not create multiple devices to do this). See
|
||||
the simple_mixing example for how best to do this.</p>
|
||||
<div style="font-family:monospace; border:solid 1px #003800; border-left:solid 0.5em #003800; margin:1em 0em;"><pre style="margin:0.5em 1em; padding:0; line-height:125%">
|
||||
#define MINIAUDIO_IMPLEMENTATION
|
||||
#include "../miniaudio.h"
|
||||
<span style="color:#666666">#define</span> MINIAUDIO_IMPLEMENTATION
|
||||
<span style="color:#666666">#include</span> <span style="color:#cc3300">"../miniaudio.h"</span>
|
||||
|
||||
#include <stdio.h>
|
||||
<span style="color:#666666">#include</span> <span style="color:#cc3300"><stdio.h></span>
|
||||
|
||||
void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount)
|
||||
<span style="color:#0033ff">void</span> data_callback(<span style="color:#0099cc">ma_device</span>* pDevice, <span style="color:#0033ff">void</span>* pOutput, <span style="color:#0033ff">const</span> <span style="color:#0033ff">void</span>* pInput, <span style="color:#0099cc">ma_uint32</span> frameCount)
|
||||
{
|
||||
ma_decoder* pDecoder = (ma_decoder*)pDevice->pUserData;
|
||||
if (pDecoder == NULL) {
|
||||
return;
|
||||
<span style="color:#0099cc">ma_decoder</span>* pDecoder = (<span style="color:#0099cc">ma_decoder</span>*)pDevice->pUserData;
|
||||
<span style="color:#0033ff">if</span> (pDecoder == NULL) {
|
||||
<span style="color:#0033ff">return</span>;
|
||||
}
|
||||
|
||||
ma_decoder_read_pcm_frames(pDecoder, pOutput, frameCount);
|
||||
|
||||
(void)pInput;
|
||||
(<span style="color:#0033ff">void</span>)pInput;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
<span style="color:#0033ff">int</span> main(<span style="color:#0033ff">int</span> argc, <span style="color:#0033ff">char</span>** argv)
|
||||
{
|
||||
ma_result result;
|
||||
ma_decoder decoder;
|
||||
ma_device_config deviceConfig;
|
||||
ma_device device;
|
||||
<span style="color:#0099cc">ma_result</span> result;
|
||||
<span style="color:#0099cc">ma_decoder</span> decoder;
|
||||
<span style="color:#0099cc">ma_device_config</span> deviceConfig;
|
||||
<span style="color:#0099cc">ma_device</span> device;
|
||||
|
||||
if (argc < 2) {
|
||||
printf("No input file.\n");
|
||||
return -1;
|
||||
<span style="color:#0033ff">if</span> (argc < 2) {
|
||||
printf(<span style="color:#cc3300">"No input file.\n"</span>);
|
||||
<span style="color:#0033ff">return</span> -1;
|
||||
}
|
||||
|
||||
result = ma_decoder_init_file(argv[1], NULL, &decoder);
|
||||
if (result != MA_SUCCESS) {
|
||||
return -2;
|
||||
<span style="color:#0033ff">if</span> (result != MA_SUCCESS) {
|
||||
<span style="color:#0033ff">return</span> -2;
|
||||
}
|
||||
|
||||
deviceConfig = ma_device_config_init(ma_device_type_playback);
|
||||
@@ -298,26 +298,26 @@ int main(int argc, char** argv)
|
||||
deviceConfig.dataCallback = data_callback;
|
||||
deviceConfig.pUserData = &decoder;
|
||||
|
||||
if (ma_device_init(NULL, &deviceConfig, &device) != MA_SUCCESS) {
|
||||
printf("Failed to open playback device.\n");
|
||||
<span style="color:#0033ff">if</span> (ma_device_init(NULL, &deviceConfig, &device) != MA_SUCCESS) {
|
||||
printf(<span style="color:#cc3300">"Failed to open playback device.\n"</span>);
|
||||
ma_decoder_uninit(&decoder);
|
||||
return -3;
|
||||
<span style="color:#0033ff">return</span> -3;
|
||||
}
|
||||
|
||||
if (ma_device_start(&device) != MA_SUCCESS) {
|
||||
printf("Failed to start playback device.\n");
|
||||
<span style="color:#0033ff">if</span> (ma_device_start(&device) != MA_SUCCESS) {
|
||||
printf(<span style="color:#cc3300">"Failed to start playback device.\n"</span>);
|
||||
ma_device_uninit(&device);
|
||||
ma_decoder_uninit(&decoder);
|
||||
return -4;
|
||||
<span style="color:#0033ff">return</span> -4;
|
||||
}
|
||||
|
||||
printf("Press Enter to quit...");
|
||||
printf(<span style="color:#cc3300">"Press Enter to quit..."</span>);
|
||||
getchar();
|
||||
|
||||
ma_device_uninit(&device);
|
||||
ma_decoder_uninit(&decoder);
|
||||
|
||||
return 0;
|
||||
<span style="color:#0033ff">return</span> 0;
|
||||
}
|
||||
</pre></div></td>
|
||||
</tr></table>
|
||||
|
||||
@@ -263,45 +263,45 @@ the <span style="font-family:monospace;">ma_waveform_read_pcm_frames()</span> AP
|
||||
|
||||
This example works with Emscripten.</p>
|
||||
<div style="font-family:monospace; border:solid 1px #003800; border-left:solid 0.5em #003800; margin:1em 0em;"><pre style="margin:0.5em 1em; padding:0; line-height:125%">
|
||||
#define MA_NO_DECODING
|
||||
#define MA_NO_ENCODING
|
||||
#define MINIAUDIO_IMPLEMENTATION
|
||||
#include "../miniaudio.h"
|
||||
<span style="color:#666666">#define</span> MA_NO_DECODING
|
||||
<span style="color:#666666">#define</span> MA_NO_ENCODING
|
||||
<span style="color:#666666">#define</span> MINIAUDIO_IMPLEMENTATION
|
||||
<span style="color:#666666">#include</span> <span style="color:#cc3300">"../miniaudio.h"</span>
|
||||
|
||||
#include <stdio.h>
|
||||
<span style="color:#666666">#include</span> <span style="color:#cc3300"><stdio.h></span>
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
#include <emscripten.h>
|
||||
<span style="color:#666666">#ifdef</span> __EMSCRIPTEN__
|
||||
<span style="color:#666666">#include</span> <span style="color:#cc3300"><emscripten.h></span>
|
||||
|
||||
void main_loop__em()
|
||||
<span style="color:#0033ff">void</span> main_loop__em()
|
||||
{
|
||||
}
|
||||
#endif
|
||||
<span style="color:#666666">#endif</span>
|
||||
|
||||
#define DEVICE_FORMAT ma_format_f32
|
||||
#define DEVICE_CHANNELS 2
|
||||
#define DEVICE_SAMPLE_RATE 48000
|
||||
<span style="color:#666666">#define</span> DEVICE_FORMAT ma_format_f32
|
||||
<span style="color:#666666">#define</span> DEVICE_CHANNELS 2
|
||||
<span style="color:#666666">#define</span> DEVICE_SAMPLE_RATE 48000
|
||||
|
||||
void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount)
|
||||
<span style="color:#0033ff">void</span> data_callback(<span style="color:#0099cc">ma_device</span>* pDevice, <span style="color:#0033ff">void</span>* pOutput, <span style="color:#0033ff">const</span> <span style="color:#0033ff">void</span>* pInput, <span style="color:#0099cc">ma_uint32</span> frameCount)
|
||||
{
|
||||
ma_waveform* pSineWave;
|
||||
<span style="color:#0099cc">ma_waveform</span>* pSineWave;
|
||||
|
||||
MA_ASSERT(pDevice->playback.channels == DEVICE_CHANNELS);
|
||||
|
||||
pSineWave = (ma_waveform*)pDevice->pUserData;
|
||||
pSineWave = (<span style="color:#0099cc">ma_waveform</span>*)pDevice->pUserData;
|
||||
MA_ASSERT(pSineWave != NULL);
|
||||
|
||||
ma_waveform_read_pcm_frames(pSineWave, pOutput, frameCount);
|
||||
|
||||
(void)pInput; /* Unused. */
|
||||
(<span style="color:#0033ff">void</span>)pInput; <span style="color:#009900">/* Unused. */</span>
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
<span style="color:#0033ff">int</span> main(<span style="color:#0033ff">int</span> argc, <span style="color:#0033ff">char</span>** argv)
|
||||
{
|
||||
ma_waveform sineWave;
|
||||
ma_device_config deviceConfig;
|
||||
ma_device device;
|
||||
ma_waveform_config sineWaveConfig;
|
||||
<span style="color:#0099cc">ma_waveform</span> sineWave;
|
||||
<span style="color:#0099cc">ma_device_config</span> deviceConfig;
|
||||
<span style="color:#0099cc">ma_device</span> device;
|
||||
<span style="color:#0099cc">ma_waveform_config</span> sineWaveConfig;
|
||||
|
||||
sineWaveConfig = ma_waveform_config_init(DEVICE_FORMAT, DEVICE_CHANNELS, DEVICE_SAMPLE_RATE, ma_waveform_type_sine, 0.2, 220);
|
||||
ma_waveform_init(&sineWaveConfig, &sineWave);
|
||||
@@ -313,31 +313,31 @@ int main(int argc, char** argv)
|
||||
deviceConfig.dataCallback = data_callback;
|
||||
deviceConfig.pUserData = &sineWave;
|
||||
|
||||
if (ma_device_init(NULL, &deviceConfig, &device) != MA_SUCCESS) {
|
||||
printf("Failed to open playback device.\n");
|
||||
return -4;
|
||||
<span style="color:#0033ff">if</span> (ma_device_init(NULL, &deviceConfig, &device) != MA_SUCCESS) {
|
||||
printf(<span style="color:#cc3300">"Failed to open playback device.\n"</span>);
|
||||
<span style="color:#0033ff">return</span> -4;
|
||||
}
|
||||
|
||||
printf("Device Name: %s\n", device.playback.name);
|
||||
printf(<span style="color:#cc3300">"Device Name: %s\n"</span>, device.playback.name);
|
||||
|
||||
if (ma_device_start(&device) != MA_SUCCESS) {
|
||||
printf("Failed to start playback device.\n");
|
||||
<span style="color:#0033ff">if</span> (ma_device_start(&device) != MA_SUCCESS) {
|
||||
printf(<span style="color:#cc3300">"Failed to start playback device.\n"</span>);
|
||||
ma_device_uninit(&device);
|
||||
return -5;
|
||||
<span style="color:#0033ff">return</span> -5;
|
||||
}
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
<span style="color:#666666">#ifdef</span> __EMSCRIPTEN__
|
||||
emscripten_set_main_loop(main_loop__em, 0, 1);
|
||||
#else
|
||||
printf("Press Enter to quit...\n");
|
||||
<span style="color:#666666">#else</span>
|
||||
printf(<span style="color:#cc3300">"Press Enter to quit...\n"</span>);
|
||||
getchar();
|
||||
#endif
|
||||
<span style="color:#666666">#endif</span>
|
||||
|
||||
ma_device_uninit(&device);
|
||||
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
return 0;
|
||||
(<span style="color:#0033ff">void</span>)argc;
|
||||
(<span style="color:#0033ff">void</span>)argv;
|
||||
<span style="color:#0033ff">return</span> 0;
|
||||
}
|
||||
</pre></div></td>
|
||||
</tr></table>
|
||||
|
||||
Reference in New Issue
Block a user