diff --git a/docs/examples/custom_backend.html b/docs/examples/custom_backend.html index a98932fc..d6a057cb 100644 --- a/docs/examples/custom_backend.html +++ b/docs/examples/custom_backend.html @@ -245,7 +245,7 @@ a.doc-navigation-l4 {
+Documentation HomeProgramming ManualExamplesCustom BackendCustom DecoderData Source ChainingFixed Size CallbackSimple CaptureSimple DuplexSimple EnumerationSimple LoopbackSimple LoopingSimple MixingSimple PlaybackSimple Playback SineAPI Reference

Custom Backend

This example show how a custom backend can be implemented.

@@ -293,9 +293,12 @@ backends would actually get hit. By default, the /* Support SDL on everything. */ #define MA_SUPPORT_SDL -/* Only enable SDL if it's hasn't been explicitly disabled (MA_NO_SDL) and it's supported at compile time (MA_SUPPORT_SDL). */ -#if !defined(MA_NO_SDL) && defined(MA_SUPPORT_SDL) - #define MA_ENABLE_SDL +/* +Only enable SDL if it's hasn't been explicitly disabled (MA_NO_SDL) or enabled (MA_ENABLE_SDL with +MA_ENABLE_ONLY_SPECIFIC_BACKENDS) and it's supported at compile time (MA_SUPPORT_SDL). +*/ +#if defined(MA_SUPPORT_SDL) && !defined(MA_NO_SDL) && (!defined(MA_ENABLE_ONLY_SPECIFIC_BACKENDS) || defined(MA_ENABLE_SDL)) + #define MA_HAS_SDL #endif @@ -331,9 +334,7 @@ backends would actually get hit. By default, the #if defined(MA_ENABLE_SDL) - #define MA_HAS_SDL - +#if defined(MA_HAS_SDL) /* SDL headers are necessary if using compile-time linking. */ #ifdef MA_NO_RUNTIME_LINKING #ifdef __has_include @@ -587,7 +588,7 @@ ma_format ma_format_from_sdl(MA_SDL_AudioFormat format) MA_ASSERT(pDeviceEx != NULL); - ma_device_handle_backend_data_callback((ma_device*)pDeviceEx, pBuffer, NULL, (ma_uint32)bufferSizeInBytes / ma_get_bytes_per_frame(pDeviceEx->device.capture.internalFormat, pDeviceEx->device.capture.internalChannels)); + ma_device_handle_backend_data_callback((ma_device*)pDeviceEx, pBuffer, NULL, (ma_uint32)bufferSizeInBytes / ma_get_bytes_per_frame(pDeviceEx->device.playback.internalFormat, pDeviceEx->device.playback.internalChannels)); } static ma_result ma_device_init_internal__sdl(ma_device_ex* pDeviceEx, const ma_device_config* pConfig, ma_device_descriptor* pDescriptor) @@ -622,22 +623,11 @@ ma_format ma_format_from_sdl(MA_SDL_AudioFormat format) Note that options 2 and 3 require knowledge of the sample rate in order to convert it to a frame count. You should try to keep the calculation of the period size as accurate as possible, but sometimes it's just not practical so just use whatever you can. + + A helper function called ma_calculate_buffer_size_in_frames_from_descriptor() is available to do all of this for you which is what + we'll be using here. */ - if (pDescriptor->periodSizeInFrames == 0) { - if (pDescriptor->periodSizeInMilliseconds == 0) { - /* The default period size has been requested. I don't think SDL has an API to retrieve this, so just using defaults defined by miniaudio. */ - if (pConfig->performanceProfile == ma_performance_profile_low_latency) { - pDescriptor->periodSizeInFrames = ma_calculate_buffer_size_in_frames_from_milliseconds(MA_DEFAULT_PERIOD_SIZE_IN_MILLISECONDS_LOW_LATENCY, pDescriptor->sampleRate); - } else { - pDescriptor->periodSizeInFrames = ma_calculate_buffer_size_in_frames_from_milliseconds(MA_DEFAULT_PERIOD_SIZE_IN_MILLISECONDS_CONSERVATIVE, pDescriptor->sampleRate); - } - } else { - /* An explicit period size in milliseconds was specified. */ - pDescriptor->periodSizeInFrames = ma_calculate_buffer_size_in_frames_from_milliseconds(pDescriptor->periodSizeInMilliseconds, pDescriptor->sampleRate); - } - } else { - /* Nothing to do here. An explicit period size in frames was specified. */ - } + pDescriptor->periodSizeInFrames = ma_calculate_buffer_size_in_frames_from_descriptor(pDescriptor, pDescriptor->sampleRate, pConfig->performanceProfile); /* SDL wants the buffer size to be a power of 2 for some reason. */ if (pDescriptor->periodSizeInFrames > 32768) { diff --git a/docs/examples/custom_decoder.html b/docs/examples/custom_decoder.html new file mode 100644 index 00000000..922ba4d5 --- /dev/null +++ b/docs/examples/custom_decoder.html @@ -0,0 +1,549 @@ + + + + miniaudio - A single file audio playback and capture library. + + + + + + + + + + + + +
+
+ + + + + + + + + +
+
+
+ + +
+

Custom Decoder

+Demonstrates how to implement a custom decoder. +

+

+ +This example implements two custom decoders: +

+
    +
  • +
  • +
+
    +
  • +Vorbis via libvorbis +
  • +
  • +Opus via libopus + +A
  • +
+

+A custom decoder must implement a data source. In this example, the libvorbis data source is called +ma_libvorbis and the Opus data source is called ma_libopus. These two objects are compatible +with the ma_data_source APIs and can be taken straight from this example and used in real code. +

+

+ +The custom decoding data sources (ma_libvorbis and ma_libopus in this example) are connected to +the decoder via the decoder config (ma_decoder_config). You need to implement a vtable for each +of your custom decoders. See ma_decoding_backend_vtable for the functions you need to implement. +The onInitFile, onInitFileW and onInitMemory functions are optional.

+
+#define MA_NO_VORBIS    /* Disable the built-in Vorbis decoder to ensure the libvorbis decoder is picked. */
+#define MA_NO_OPUS      /* Disable the (not yet implemented) built-in Opus decoder to ensure the libopus decoder is picked. */
+#define MINIAUDIO_IMPLEMENTATION
+#include "../miniaudio.h"
+#include "../extras/miniaudio_libvorbis.h"
+#include "../extras/miniaudio_libopus.h"
+
+#include <stdio.h>
+
+static ma_result ma_decoding_backend_init__libvorbis(void* pUserData, ma_read_proc onRead, ma_seek_proc onSeek, ma_tell_proc onTell, void* pReadSeekTellUserData, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_data_source** ppBackend)
+{
+    ma_result result;
+    ma_libvorbis* pVorbis;
+
+    (void)pUserData;
+
+    pVorbis = (ma_libvorbis*)ma_malloc(sizeof(*pVorbis), pAllocationCallbacks);
+    if (pVorbis == NULL) {
+        return MA_OUT_OF_MEMORY;
+    }
+
+    result = ma_libvorbis_init(onRead, onSeek, onTell, pReadSeekTellUserData, pConfig, pAllocationCallbacks, pVorbis);
+    if (result != MA_SUCCESS) {
+        ma_free(pVorbis, pAllocationCallbacks);
+        return result;
+    }
+
+    *ppBackend = pVorbis;
+
+    return MA_SUCCESS;
+}
+
+static ma_result ma_decoding_backend_init_file__libvorbis(void* pUserData, const char* pFilePath, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_data_source** ppBackend)
+{
+    ma_result result;
+    ma_libvorbis* pVorbis;
+
+    (void)pUserData;
+
+    pVorbis = (ma_libvorbis*)ma_malloc(sizeof(*pVorbis), pAllocationCallbacks);
+    if (pVorbis == NULL) {
+        return MA_OUT_OF_MEMORY;
+    }
+
+    result = ma_libvorbis_init_file(pFilePath, pConfig, pAllocationCallbacks, pVorbis);
+    if (result != MA_SUCCESS) {
+        ma_free(pVorbis, pAllocationCallbacks);
+        return result;
+    }
+
+    *ppBackend = pVorbis;
+
+    return MA_SUCCESS;
+}
+
+static void ma_decoding_backend_uninit__libvorbis(void* pUserData, ma_data_source* pBackend, const ma_allocation_callbacks* pAllocationCallbacks)
+{
+    ma_libvorbis* pVorbis = (ma_libvorbis*)pBackend;
+
+    (void)pUserData;
+
+    ma_libvorbis_uninit(pVorbis, pAllocationCallbacks);
+    ma_free(pVorbis, pAllocationCallbacks);
+}
+
+static ma_result ma_decoding_backend_get_channel_map__libvorbis(void* pUserData, ma_data_source* pBackend, ma_channel* pChannelMap, size_t channelMapCap)
+{
+    ma_libvorbis* pVorbis = (ma_libvorbis*)pBackend;
+
+    (void)pUserData;
+
+    return ma_libvorbis_get_data_format(pVorbis, NULL, NULL, NULL, pChannelMap, channelMapCap);
+}
+
+static ma_decoding_backend_vtable g_ma_decoding_backend_vtable_libvorbis =
+{
+    ma_decoding_backend_init__libvorbis,
+    ma_decoding_backend_init_file__libvorbis,
+    NULL, /* onInitFileW() */
+    NULL, /* onInitMemory() */
+    ma_decoding_backend_uninit__libvorbis,
+    ma_decoding_backend_get_channel_map__libvorbis
+};
+
+
+
+static ma_result ma_decoding_backend_init__libopus(void* pUserData, ma_read_proc onRead, ma_seek_proc onSeek, ma_tell_proc onTell, void* pReadSeekTellUserData, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_data_source** ppBackend)
+{
+    ma_result result;
+    ma_libopus* pOpus;
+
+    (void)pUserData;
+
+    pOpus = (ma_libopus*)ma_malloc(sizeof(*pOpus), pAllocationCallbacks);
+    if (pOpus == NULL) {
+        return MA_OUT_OF_MEMORY;
+    }
+
+    result = ma_libopus_init(onRead, onSeek, onTell, pReadSeekTellUserData, pConfig, pAllocationCallbacks, pOpus);
+    if (result != MA_SUCCESS) {
+        ma_free(pOpus, pAllocationCallbacks);
+        return result;
+    }
+
+    *ppBackend = pOpus;
+
+    return MA_SUCCESS;
+}
+
+static ma_result ma_decoding_backend_init_file__libopus(void* pUserData, const char* pFilePath, const ma_decoding_backend_config* pConfig, const ma_allocation_callbacks* pAllocationCallbacks, ma_data_source** ppBackend)
+{
+    ma_result result;
+    ma_libopus* pOpus;
+
+    (void)pUserData;
+
+    pOpus = (ma_libopus*)ma_malloc(sizeof(*pOpus), pAllocationCallbacks);
+    if (pOpus == NULL) {
+        return MA_OUT_OF_MEMORY;
+    }
+
+    result = ma_libopus_init_file(pFilePath, pConfig, pAllocationCallbacks, pOpus);
+    if (result != MA_SUCCESS) {
+        ma_free(pOpus, pAllocationCallbacks);
+        return result;
+    }
+
+    *ppBackend = pOpus;
+
+    return MA_SUCCESS;
+}
+
+static void ma_decoding_backend_uninit__libopus(void* pUserData, ma_data_source* pBackend, const ma_allocation_callbacks* pAllocationCallbacks)
+{
+    ma_libopus* pOpus = (ma_libopus*)pBackend;
+
+    (void)pUserData;
+
+    ma_libopus_uninit(pOpus, pAllocationCallbacks);
+    ma_free(pOpus, pAllocationCallbacks);
+}
+
+static ma_result ma_decoding_backend_get_channel_map__libopus(void* pUserData, ma_data_source* pBackend, ma_channel* pChannelMap, size_t channelMapCap)
+{
+    ma_libopus* pOpus = (ma_libopus*)pBackend;
+
+    (void)pUserData;
+
+    return ma_libopus_get_data_format(pOpus, NULL, NULL, NULL, pChannelMap, channelMapCap);
+}
+
+static ma_decoding_backend_vtable g_ma_decoding_backend_vtable_libopus =
+{
+    ma_decoding_backend_init__libopus,
+    ma_decoding_backend_init_file__libopus,
+    NULL, /* onInitFileW() */
+    NULL, /* onInitMemory() */
+    ma_decoding_backend_uninit__libopus,
+    ma_decoding_backend_get_channel_map__libopus
+};
+
+
+
+
+void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount)
+{
+    ma_data_source* pDataSource = (ma_data_source*)pDevice->pUserData;
+    if (pDataSource == NULL) {
+        return;
+    }
+
+    ma_data_source_read_pcm_frames(pDataSource, pOutput, frameCount, NULL, MA_TRUE);
+
+    (void)pInput;
+}
+
+int main(int argc, char** argv)
+{
+    ma_result result;
+    ma_decoder_config decoderConfig;
+    ma_decoder decoder;
+    ma_device_config deviceConfig;
+    ma_device device;
+    ma_format format;
+    ma_uint32 channels;
+    ma_uint32 sampleRate;
+
+    /*
+    Add your custom backend vtables here. The order in the array defines the order of priority. The
+    vtables will be passed in via the decoder config.
+    */
+    ma_decoding_backend_vtable* pCustomBackendVTables[] =
+    {
+        &g_ma_decoding_backend_vtable_libvorbis,
+        &g_ma_decoding_backend_vtable_libopus
+    };
+
+
+    if (argc < 2) {
+        printf("No input file.\n");
+        return -1;
+    }
+
+    
+    /* Initialize the decoder. */
+    decoderConfig = ma_decoder_config_init_default();
+    decoderConfig.pCustomBackendUserData = NULL;  /* In this example our backend objects are contained within a ma_decoder_ex object to avoid a malloc. Our vtables need to know about this. */
+    decoderConfig.ppCustomBackendVTables = pCustomBackendVTables;
+    decoderConfig.customBackendCount     = sizeof(pCustomBackendVTables) / sizeof(pCustomBackendVTables[0]);
+    
+    result = ma_decoder_init_file(argv[1], &decoderConfig, &decoder);
+    if (result != MA_SUCCESS) {
+        printf("Failed to initialize decoder.");
+        return -1;
+    }
+
+
+    /* Initialize the device. */
+    result = ma_data_source_get_data_format(&decoder, &format, &channels, &sampleRate);
+    if (result != MA_SUCCESS) {
+        printf("Failed to retrieve decoder data format.");
+        ma_decoder_uninit(&decoder);
+        return -1;
+    }
+
+    deviceConfig = ma_device_config_init(ma_device_type_playback);
+    deviceConfig.playback.format   = format;
+    deviceConfig.playback.channels = channels;
+    deviceConfig.sampleRate        = sampleRate;
+    deviceConfig.dataCallback      = data_callback;
+    deviceConfig.pUserData         = &decoder;
+
+    if (ma_device_init(NULL, &deviceConfig, &device) != MA_SUCCESS) {
+        printf("Failed to open playback device.\n");
+        ma_decoder_uninit(&decoder);
+        return -1;
+    }
+
+    if (ma_device_start(&device) != MA_SUCCESS) {
+        printf("Failed to start playback device.\n");
+        ma_device_uninit(&device);
+        ma_decoder_uninit(&decoder);
+        return -1;
+    }
+
+    printf("Press Enter to quit...");
+    getchar();
+
+    ma_device_uninit(&device);
+    ma_decoder_uninit(&decoder);
+
+    return 0;
+}
+
+ + + + + + +
+ +
+ Copyright © 2021 David Reid
+ Developed by David Reid - mackron@gmail.com +
+ + diff --git a/docs/examples/fixed_size_callback.html b/docs/examples/fixed_size_callback.html index 00b57299..33cdfe9d 100644 --- a/docs/examples/fixed_size_callback.html +++ b/docs/examples/fixed_size_callback.html @@ -245,7 +245,7 @@ a.doc-navigation-l4 {
+Documentation HomeProgramming ManualExamplesCustom BackendCustom DecoderData Source ChainingFixed Size CallbackSimple CaptureSimple DuplexSimple EnumerationSimple LoopbackSimple LoopingSimple MixingSimple PlaybackSimple Playback SineAPI Reference

Fixed Size Callback

Shows one way to implement a data callback that is called with a fixed frame count.

diff --git a/docs/examples/index.html b/docs/examples/index.html index a5e56e36..9e34da22 100644 --- a/docs/examples/index.html +++ b/docs/examples/index.html @@ -245,9 +245,10 @@ a.doc-navigation-l4 {
+
+Documentation HomeProgramming ManualExamplesCustom BackendCustom DecoderData Source ChainingFixed Size CallbackSimple CaptureSimple DuplexSimple EnumerationSimple LoopbackSimple LoopingSimple MixingSimple PlaybackSimple Playback SineAPI Reference -
Custom BackendThis example show how a custom backend can be implemented.
Fixed Size CallbackShows one way to implement a data callback that is called with a fixed frame count.
Simple CaptureDemonstrates how to capture data from a microphone using the low-level API.
Simple DuplexDemonstrates duplex mode which is where data is captured from a microphone and then output to a speaker device.
Simple EnumerationDemonstrates how to enumerate over devices.
Simple LoopbackDemonstrates how to implement loopback recording.
Simple LoopingShows one way to handle looping of a sound.
Simple MixingDemonstrates one way to load multiple files and play them all back at the same time.
Simple PlaybackDemonstrates how to load a sound file and play it back using the low-level API.
Simple Playback SineDemonstrates playback of a sine wave.
Custom BackendThis example show how a custom backend can be implemented.
Custom DecoderDemonstrates how to implement a custom decoder.
Data Source ChainingDemonstrates one way to chain together a number of data sources so they play back seamlessly +without gaps.
Fixed Size CallbackShows one way to implement a data callback that is called with a fixed frame count.
Simple CaptureDemonstrates how to capture data from a microphone using the low-level API.
Simple DuplexDemonstrates duplex mode which is where data is captured from a microphone and then output to a speaker device.
Simple EnumerationDemonstrates how to enumerate over devices.
Simple LoopbackDemonstrates how to implement loopback recording.
Simple LoopingShows one way to handle looping of a sound.
Simple MixingDemonstrates one way to load multiple files and play them all back at the same time.
Simple PlaybackDemonstrates how to load a sound file and play it back using the low-level API.
Simple Playback SineDemonstrates playback of a sine wave.
diff --git a/docs/examples/simple_capture.html b/docs/examples/simple_capture.html index cb1f89ea..8546a8e1 100644 --- a/docs/examples/simple_capture.html +++ b/docs/examples/simple_capture.html @@ -245,7 +245,7 @@ a.doc-navigation-l4 {
+Documentation HomeProgramming ManualExamplesCustom BackendCustom DecoderData Source ChainingFixed Size CallbackSimple CaptureSimple DuplexSimple EnumerationSimple LoopbackSimple LoopingSimple MixingSimple PlaybackSimple Playback SineAPI Reference

Simple Capture

Demonstrates how to capture data from a microphone using the low-level API.

@@ -285,7 +285,7 @@ data received by the microphone straight to a WAV file.

ma_device device; if (argc < 2) { - printf("No input file.\n"); + printf("No output file.\n"); return -1; } diff --git a/docs/examples/simple_duplex.html b/docs/examples/simple_duplex.html index c1dec4e8..904683f2 100644 --- a/docs/examples/simple_duplex.html +++ b/docs/examples/simple_duplex.html @@ -245,7 +245,7 @@ a.doc-navigation-l4 {
+Documentation HomeProgramming ManualExamplesCustom BackendCustom DecoderData Source ChainingFixed Size CallbackSimple CaptureSimple DuplexSimple EnumerationSimple LoopbackSimple LoopingSimple MixingSimple PlaybackSimple Playback SineAPI Reference

Simple Duplex

Demonstrates duplex mode which is where data is captured from a microphone and then output to a speaker device.

diff --git a/docs/examples/simple_enumeration.html b/docs/examples/simple_enumeration.html index df538919..d217fbc4 100644 --- a/docs/examples/simple_enumeration.html +++ b/docs/examples/simple_enumeration.html @@ -245,7 +245,7 @@ a.doc-navigation-l4 {
+Documentation HomeProgramming ManualExamplesCustom BackendCustom DecoderData Source ChainingFixed Size CallbackSimple CaptureSimple DuplexSimple EnumerationSimple LoopbackSimple LoopingSimple MixingSimple PlaybackSimple Playback SineAPI Reference

Simple Enumeration

Demonstrates how to enumerate over devices.

diff --git a/docs/examples/simple_loopback.html b/docs/examples/simple_loopback.html index 02823cff..66fa9605 100644 --- a/docs/examples/simple_loopback.html +++ b/docs/examples/simple_loopback.html @@ -245,7 +245,7 @@ a.doc-navigation-l4 {
+Documentation HomeProgramming ManualExamplesCustom BackendCustom DecoderData Source ChainingFixed Size CallbackSimple CaptureSimple DuplexSimple EnumerationSimple LoopbackSimple LoopingSimple MixingSimple PlaybackSimple Playback SineAPI Reference

Simple Loopback

Demonstrates how to implement loopback recording.

@@ -294,7 +294,7 @@ properties. The output buffer in the callback will be null whereas the input buf }; if (argc < 2) { - printf("No input file.\n"); + printf("No output file.\n"); return -1; } diff --git a/docs/examples/simple_looping.html b/docs/examples/simple_looping.html index a50c2b40..1a295663 100644 --- a/docs/examples/simple_looping.html +++ b/docs/examples/simple_looping.html @@ -245,7 +245,7 @@ a.doc-navigation-l4 {
+Documentation HomeProgramming ManualExamplesCustom BackendCustom DecoderData Source ChainingFixed Size CallbackSimple CaptureSimple DuplexSimple EnumerationSimple LoopbackSimple LoopingSimple MixingSimple PlaybackSimple Playback SineAPI Reference

Simple Looping

Shows one way to handle looping of a sound.

diff --git a/docs/examples/simple_mixing.html b/docs/examples/simple_mixing.html index e8b1a00a..4c1a1baa 100644 --- a/docs/examples/simple_mixing.html +++ b/docs/examples/simple_mixing.html @@ -245,7 +245,7 @@ a.doc-navigation-l4 {
+Documentation HomeProgramming ManualExamplesCustom BackendCustom DecoderData Source ChainingFixed Size CallbackSimple CaptureSimple DuplexSimple EnumerationSimple LoopbackSimple LoopingSimple MixingSimple PlaybackSimple Playback SineAPI Reference

Simple Mixing

Demonstrates one way to load multiple files and play them all back at the same time.

diff --git a/docs/examples/simple_playback.html b/docs/examples/simple_playback.html index e93a997a..bf4700e0 100644 --- a/docs/examples/simple_playback.html +++ b/docs/examples/simple_playback.html @@ -245,7 +245,7 @@ a.doc-navigation-l4 {
+Documentation HomeProgramming ManualExamplesCustom BackendCustom DecoderData Source ChainingFixed Size CallbackSimple CaptureSimple DuplexSimple EnumerationSimple LoopbackSimple LoopingSimple MixingSimple PlaybackSimple Playback SineAPI Reference

Simple Playback

Demonstrates how to load a sound file and play it back using the low-level API.

@@ -293,6 +293,7 @@ the simple_mixing example for how best to do this.

result = ma_decoder_init_file(argv[1], NULL, &decoder); if (result != MA_SUCCESS) { + printf("Could not load file: %s\n", argv[1]); return -2; } diff --git a/docs/examples/simple_playback_sine.html b/docs/examples/simple_playback_sine.html index a2ecb8cf..953f6eec 100644 --- a/docs/examples/simple_playback_sine.html +++ b/docs/examples/simple_playback_sine.html @@ -245,7 +245,7 @@ a.doc-navigation-l4 {
- - - - @@ -1493,21 +1467,19 @@ ma_decoder_seek_to_pcm_frame(pDecoder, 0);

When loading a decoder, miniaudio uses a trial and error technique to find the appropriate decoding backend. This can be unnecessarily inefficient if the type -is already known. In this case you can use the _wav, _mp3, etc. varients of the aforementioned initialization APIs: +is already known. In this case you can use encodingFormat variable in the device config to specify a specific encoding format you want to decode:

-ma_decoder_init_wav()
-ma_decoder_init_mp3()
-ma_decoder_init_memory_wav()
-ma_decoder_init_memory_mp3()
-ma_decoder_init_file_wav()
-ma_decoder_init_file_mp3()
-etc.
+decoderConfig.encodingFormat = ma_encoding_format_wav;
 

+See the ma_encoding_format enum for possible encoding formats. +

+

+ The ma_decoder_init_file() API will try using the file extension to determine which decoding backend to prefer.

+Documentation HomeProgramming ManualExamplesCustom BackendCustom DecoderData Source ChainingFixed Size CallbackSimple CaptureSimple DuplexSimple EnumerationSimple LoopbackSimple LoopingSimple MixingSimple PlaybackSimple Playback SineAPI Reference

Simple Playback Sine

Demonstrates playback of a sine wave.

diff --git a/docs/manual/index.html b/docs/manual/index.html index c158b8b1..23884288 100644 --- a/docs/manual/index.html +++ b/docs/manual/index.html @@ -1126,38 +1126,12 @@ runtime linking via dlopen().

-MA_LOG_LEVEL [level] - -

-

- - -

-

- - -

-

- +MA_DEBUG_OUTPUT

-Sets the logging level. Set level to one of the following: - -

-
-MA_LOG_LEVEL_VERBOSE
-MA_LOG_LEVEL_INFO
-MA_LOG_LEVEL_WARNING
-MA_LOG_LEVEL_ERROR
-

-MA_DEBUG_OUTPUT

-

-Enable printf() debug output.

+Enable processing of MA_LOG_LEVEL_DEBUG messages and printf() +output.