Commit 8bcf9792 authored by David Reid's avatar David Reid

Updates to documentation.

parent 2e836e3e
...@@ -34,8 +34,9 @@ but you could allocate it on the heap if that suits your situation better. ...@@ -34,8 +34,9 @@ but you could allocate it on the heap if that suits your situation better.
```c ```c
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)
{ {
// In playback mode copy data to pOutput. In capture mode read data from pInput. In full-duplex mode, both pOutput and pInput will be valid and you can // In playback mode copy data to pOutput. In capture mode read data from pInput. In full-duplex mode, both
// move data from pInput into pOutput. Never process more than frameCount frames. // pOutput and pInput will be valid and you can move data from pInput into pOutput. Never process more than
// frameCount frames.
} }
... ...
...@@ -715,7 +716,8 @@ The following example shows how data can be processed ...@@ -715,7 +716,8 @@ The following example shows how data can be processed
// An error occurred... // An error occurred...
} }
// At this point, frameCountIn contains the number of input frames that were consumed and frameCountOut contains the number of output frames written. // At this point, frameCountIn contains the number of input frames that were consumed and frameCountOut contains the
// number of output frames written.
``` ```
To initialize the resampler you first need to set up a config (`ma_resampler_config`) with `ma_resampler_config_init()`. You need to specify the sample format To initialize the resampler you first need to set up a config (`ma_resampler_config`) with `ma_resampler_config_init()`. You need to specify the sample format
...@@ -792,12 +794,16 @@ The Speex resampler is made up of third party code which is released under the B ...@@ -792,12 +794,16 @@ The Speex resampler is made up of third party code which is released under the B
domain, it is strictly opt-in and all of it's code is stored in separate files. If you opt-in to the Speex resampler you must consider the license text in it's domain, it is strictly opt-in and all of it's code is stored in separate files. If you opt-in to the Speex resampler you must consider the license text in it's
source files. To opt-in, you must first #include the following file before the implementation of miniaudio.h: source files. To opt-in, you must first #include the following file before the implementation of miniaudio.h:
```c
#include "extras/speex_resampler/ma_speex_resampler.h" #include "extras/speex_resampler/ma_speex_resampler.h"
```
Both the header and implementation is contained within the same file. The implementation can be included in your program like so: Both the header and implementation is contained within the same file. The implementation can be included in your program like so:
```c
#define MINIAUDIO_SPEEX_RESAMPLER_IMPLEMENTATION #define MINIAUDIO_SPEEX_RESAMPLER_IMPLEMENTATION
#include "extras/speex_resampler/ma_speex_resampler.h" #include "extras/speex_resampler/ma_speex_resampler.h"
```
Note that even if you opt-in to the Speex backend, miniaudio won't use it unless you explicitly ask for it in the respective config of the object you are Note that even if you opt-in to the Speex backend, miniaudio won't use it unless you explicitly ask for it in the respective config of the object you are
initializing. If you try to use the Speex resampler without opting in, initialization of the `ma_resampler` object will fail with `MA_NO_BACKEND`. initializing. If you try to use the Speex resampler without opting in, initialization of the `ma_resampler` object will fail with `MA_NO_BACKEND`.
...@@ -814,7 +820,15 @@ internally to convert between the format requested when the device was initializ ...@@ -814,7 +820,15 @@ internally to convert between the format requested when the device was initializ
conversion is very similar to the resampling API. Create a `ma_data_converter` object like this: conversion is very similar to the resampling API. Create a `ma_data_converter` object like this:
```c ```c
ma_data_converter_config config = ma_data_converter_config_init(inputFormat, outputFormat, inputChannels, outputChannels, inputSampleRate, outputSampleRate); ma_data_converter_config config = ma_data_converter_config_init(
inputFormat,
outputFormat,
inputChannels,
outputChannels,
inputSampleRate,
outputSampleRate
);
ma_data_converter converter; ma_data_converter converter;
ma_result result = ma_data_converter_init(&config, &converter); ma_result result = ma_data_converter_init(&config, &converter);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
...@@ -853,7 +867,8 @@ The following example shows how data can be processed ...@@ -853,7 +867,8 @@ The following example shows how data can be processed
// An error occurred... // An error occurred...
} }
// At this point, frameCountIn contains the number of input frames that were consumed and frameCountOut contains the number of output frames written. // At this point, frameCountIn contains the number of input frames that were consumed and frameCountOut contains the number
// of output frames written.
``` ```
The data converter supports multiple channels and is always interleaved (both input and output). The channel count cannot be changed after initialization. The data converter supports multiple channels and is always interleaved (both input and output). The channel count cannot be changed after initialization.
...@@ -1161,6 +1176,7 @@ Sometimes it can be convenient to allocate the memory for the `ma_audio_buffer` ...@@ -1161,6 +1176,7 @@ Sometimes it can be convenient to allocate the memory for the `ma_audio_buffer`
the raw audio data will be located immediately after the `ma_audio_buffer` structure. To do this, use `ma_audio_buffer_alloc_and_init()`: the raw audio data will be located immediately after the `ma_audio_buffer` structure. To do this, use `ma_audio_buffer_alloc_and_init()`:
```c ```c
ma_audio_buffer_config config = ma_audio_buffer_config_init(format, channels, sizeInFrames, pExistingData, &allocationCallbacks);
ma_audio_buffer* pBuffer ma_audio_buffer* pBuffer
result = ma_audio_buffer_alloc_and_init(&config, &pBuffer); result = ma_audio_buffer_alloc_and_init(&config, &pBuffer);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
...@@ -1172,13 +1188,13 @@ the raw audio data will be located immediately after the `ma_audio_buffer` struc ...@@ -1172,13 +1188,13 @@ the raw audio data will be located immediately after the `ma_audio_buffer` struc
ma_audio_buffer_uninit_and_free(&buffer); ma_audio_buffer_uninit_and_free(&buffer);
``` ```
If you initialize the buffer with `ma_audio_buffer_alloc_and_init()` you should uninitialize it with `ma_audio_buffer_uninit_and_free()`. If you initialize the buffer with `ma_audio_buffer_alloc_and_init()` you should uninitialize it with `ma_audio_buffer_uninit_and_free()`. In the example above,
the memory pointed to by `pExistingData` will be copied into the buffer, which is contrary to the behavior of `ma_audio_buffer_init()`.
An audio buffer has a playback cursor just like a decoder. As you read frames from the buffer, the cursor moves forward. It does not automatically loop back to An audio buffer has a playback cursor just like a decoder. As you read frames from the buffer, the cursor moves forward. The last parameter (`loop`) can be
the start. To do this, you should inspect the number of frames returned by `ma_audio_buffer_read_pcm_frames()` to determine if the end has been reached, which used to determine if the buffer should loop. The return value is the number of frames actually read. If this is less than the number of frames requested it
you can know by comparing it with the requested frame count you specified when you called the function. If the return value is less it means the end has been means the end has been reached. This should never happen if the `loop` parameter is set to true. If you want to manually loop back to the start, you can do so
reached. In this case you can seem back to the start with `ma_audio_buffer_seek_to_pcm_frame(pAudioBuffer, 0)`. Below is an example for reading data from an with with `ma_audio_buffer_seek_to_pcm_frame(pAudioBuffer, 0)`. Below is an example for reading data from an audio buffer.
audio buffer.
```c ```c
ma_uint64 framesRead = ma_audio_buffer_read_pcm_frames(pAudioBuffer, pFramesOut, desiredFrameCount, isLooping); ma_uint64 framesRead = ma_audio_buffer_read_pcm_frames(pAudioBuffer, pFramesOut, desiredFrameCount, isLooping);
...@@ -1187,15 +1203,16 @@ audio buffer. ...@@ -1187,15 +1203,16 @@ audio buffer.
} }
``` ```
Sometimes you may want to avoid the cost of data movement between the internal buffer and the output buffer as it's just a copy operation. Instead you can use Sometimes you may want to avoid the cost of data movement between the internal buffer and the output buffer. Instead you can use memory mapping to retrieve a
memory mapping to retrieve a pointer to a segment of data: pointer to a segment of data:
```c ```c
void* pMappedFrames; void* pMappedFrames;
ma_uint64 frameCount = frameCountToTryMapping; ma_uint64 frameCount = frameCountToTryMapping;
ma_result result = ma_audio_buffer_map(pAudioBuffer, &pMappedFrames, &frameCount); ma_result result = ma_audio_buffer_map(pAudioBuffer, &pMappedFrames, &frameCount);
if (result == MA_SUCCESS) { if (result == MA_SUCCESS) {
// Map was successful. The value in frameCount will be how many frames were _actually_ mapped, which may be less due to the end of the buffer being reached. // Map was successful. The value in frameCount will be how many frames were _actually_ mapped, which may be
// less due to the end of the buffer being reached.
ma_copy_pcm_frames(pFramesOut, pMappedFrames, frameCount, pAudioBuffer->format, pAudioBuffer->channels); ma_copy_pcm_frames(pFramesOut, pMappedFrames, frameCount, pAudioBuffer->format, pAudioBuffer->channels);
// You must unmap the buffer. // You must unmap the buffer.
...@@ -1205,7 +1222,8 @@ memory mapping to retrieve a pointer to a segment of data: ...@@ -1205,7 +1222,8 @@ memory mapping to retrieve a pointer to a segment of data:
When you use memory mapping, the read cursor is increment by the frame count passed in to `ma_audio_buffer_unmap()`. If you decide not to process every frame When you use memory mapping, the read cursor is increment by the frame count passed in to `ma_audio_buffer_unmap()`. If you decide not to process every frame
you can pass in a value smaller than the value returned by `ma_audio_buffer_map()`. The disadvantage to using memory mapping is that it does not handle looping you can pass in a value smaller than the value returned by `ma_audio_buffer_map()`. The disadvantage to using memory mapping is that it does not handle looping
for you. You can determine if the buffer is at the end for the purpose of looping with `ma_audio_buffer_at_end()`. for you. You can determine if the buffer is at the end for the purpose of looping with `ma_audio_buffer_at_end()` or by inspecting the return value of
`ma_audio_buffer_unmap()` and checking if it equals `MA_AT_END`. You should not treat `MA_AT_END` as an error when returned by `ma_audio_buffer_unmap()`.
...@@ -39,4 +39,4 @@ ...@@ -39,4 +39,4 @@
</table> </table>
</div> </div>
</div> </div>
<div style="background-color:#fff; padding-bottom:1em; border-top:solid 1px #333; background-color:#eee;"> <div style="background-color:#fff; padding-bottom:1em; border-top:solid 1px #003800; background-color:#eee;">
\ No newline at end of file \ No newline at end of file
...@@ -122,8 +122,8 @@ th.doc, td.doc { ...@@ -122,8 +122,8 @@ th.doc, td.doc {
} }
th.doc { th.doc {
border:solid 1px #030; border:solid 1px #003800;
background-color:#030; background-color:#003800;
color:#FFF; color:#FFF;
text-align:left; text-align:left;
} }
...@@ -132,7 +132,53 @@ td.doc { ...@@ -132,7 +132,53 @@ td.doc {
border:solid 1px #666; border:solid 1px #666;
} }
td p, th p { td.doc p, th.doc p {
padding:0; padding:0;
margin:0; margin:0;
} }
a.doc-navigation {
display:block;
padding:0.5em;
color:#003800;
border-bottom:solid 1px #bbbbbb;
}
a.doc-navigation:hover {
color:#fff;
background-color:#003800;
text-decoration:none;
/*border-bottom:solid 1px #003800;*/
}
/*
a.doc-navigation:hover {
background-color:#c5ecc5;
text-decoration:none;
}
*/
a.doc-navigation-active {
background-color:#cccccc;
}
a.doc-navigation-active:hover {
color:#003800;
background-color:#cccccc;
}
a.doc-navigation-l1 {
padding:0.1em;
padding-left:1.5em;
}
a.doc-navigation-l2 {
padding:0.1em;
padding-left:3em;
}
a.doc-navigation-l3 {
padding:0.1em;
padding-left:4em;
}
a.doc-navigation-l4 {
padding:0.1em;
padding-left:5em;
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment