pvrecorder/src/miniaudio/examples/custom_decoder.c
Go to the documentation of this file.
1 /*
2 Demonstrates how to implement a custom decoder.
3 
4 This example implements two custom decoders:
5 
6  * Vorbis via libvorbis
7  * Opus via libopus
8 
9 A custom decoder must implement a data source. In this example, the libvorbis data source is called
10 `ma_libvorbis` and the Opus data source is called `ma_libopus`. These two objects are compatible
11 with the `ma_data_source` APIs and can be taken straight from this example and used in real code.
12 
13 The custom decoding data sources (`ma_libvorbis` and `ma_libopus` in this example) are connected to
14 the decoder via the decoder config (`ma_decoder_config`). You need to implement a vtable for each
15 of your custom decoders. See `ma_decoding_backend_vtable` for the functions you need to implement.
16 The `onInitFile`, `onInitFileW` and `onInitMemory` functions are optional.
17 */
18 #define MA_NO_VORBIS /* Disable the built-in Vorbis decoder to ensure the libvorbis decoder is picked. */
19 #define MA_NO_OPUS /* Disable the (not yet implemented) built-in Opus decoder to ensure the libopus decoder is picked. */
20 #define MINIAUDIO_IMPLEMENTATION
21 #include "../miniaudio.h"
22 #include "../extras/miniaudio_libvorbis.h"
23 #include "../extras/miniaudio_libopus.h"
24 
25 #include <stdio.h>
26 
27 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)
28 {
29  ma_result result;
30  ma_libvorbis* pVorbis;
31 
32  (void)pUserData;
33 
34  pVorbis = (ma_libvorbis*)ma_malloc(sizeof(*pVorbis), pAllocationCallbacks);
35  if (pVorbis == NULL) {
36  return MA_OUT_OF_MEMORY;
37  }
38 
39  result = ma_libvorbis_init(onRead, onSeek, onTell, pReadSeekTellUserData, pConfig, pAllocationCallbacks, pVorbis);
40  if (result != MA_SUCCESS) {
41  ma_free(pVorbis, pAllocationCallbacks);
42  return result;
43  }
44 
45  *ppBackend = pVorbis;
46 
47  return MA_SUCCESS;
48 }
49 
50 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)
51 {
52  ma_result result;
53  ma_libvorbis* pVorbis;
54 
55  (void)pUserData;
56 
57  pVorbis = (ma_libvorbis*)ma_malloc(sizeof(*pVorbis), pAllocationCallbacks);
58  if (pVorbis == NULL) {
59  return MA_OUT_OF_MEMORY;
60  }
61 
62  result = ma_libvorbis_init_file(pFilePath, pConfig, pAllocationCallbacks, pVorbis);
63  if (result != MA_SUCCESS) {
64  ma_free(pVorbis, pAllocationCallbacks);
65  return result;
66  }
67 
68  *ppBackend = pVorbis;
69 
70  return MA_SUCCESS;
71 }
72 
73 static void ma_decoding_backend_uninit__libvorbis(void* pUserData, ma_data_source* pBackend, const ma_allocation_callbacks* pAllocationCallbacks)
74 {
75  ma_libvorbis* pVorbis = (ma_libvorbis*)pBackend;
76 
77  (void)pUserData;
78 
79  ma_libvorbis_uninit(pVorbis, pAllocationCallbacks);
80  ma_free(pVorbis, pAllocationCallbacks);
81 }
82 
83 static ma_result ma_decoding_backend_get_channel_map__libvorbis(void* pUserData, ma_data_source* pBackend, ma_channel* pChannelMap, size_t channelMapCap)
84 {
85  ma_libvorbis* pVorbis = (ma_libvorbis*)pBackend;
86 
87  (void)pUserData;
88 
89  return ma_libvorbis_get_data_format(pVorbis, NULL, NULL, NULL, pChannelMap, channelMapCap);
90 }
91 
93 {
96  NULL, /* onInitFileW() */
97  NULL, /* onInitMemory() */
100 };
101 
102 
103 
104 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)
105 {
106  ma_result result;
107  ma_libopus* pOpus;
108 
109  (void)pUserData;
110 
111  pOpus = (ma_libopus*)ma_malloc(sizeof(*pOpus), pAllocationCallbacks);
112  if (pOpus == NULL) {
113  return MA_OUT_OF_MEMORY;
114  }
115 
116  result = ma_libopus_init(onRead, onSeek, onTell, pReadSeekTellUserData, pConfig, pAllocationCallbacks, pOpus);
117  if (result != MA_SUCCESS) {
118  ma_free(pOpus, pAllocationCallbacks);
119  return result;
120  }
121 
122  *ppBackend = pOpus;
123 
124  return MA_SUCCESS;
125 }
126 
127 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)
128 {
129  ma_result result;
130  ma_libopus* pOpus;
131 
132  (void)pUserData;
133 
134  pOpus = (ma_libopus*)ma_malloc(sizeof(*pOpus), pAllocationCallbacks);
135  if (pOpus == NULL) {
136  return MA_OUT_OF_MEMORY;
137  }
138 
139  result = ma_libopus_init_file(pFilePath, pConfig, pAllocationCallbacks, pOpus);
140  if (result != MA_SUCCESS) {
141  ma_free(pOpus, pAllocationCallbacks);
142  return result;
143  }
144 
145  *ppBackend = pOpus;
146 
147  return MA_SUCCESS;
148 }
149 
150 static void ma_decoding_backend_uninit__libopus(void* pUserData, ma_data_source* pBackend, const ma_allocation_callbacks* pAllocationCallbacks)
151 {
152  ma_libopus* pOpus = (ma_libopus*)pBackend;
153 
154  (void)pUserData;
155 
156  ma_libopus_uninit(pOpus, pAllocationCallbacks);
157  ma_free(pOpus, pAllocationCallbacks);
158 }
159 
160 static ma_result ma_decoding_backend_get_channel_map__libopus(void* pUserData, ma_data_source* pBackend, ma_channel* pChannelMap, size_t channelMapCap)
161 {
162  ma_libopus* pOpus = (ma_libopus*)pBackend;
163 
164  (void)pUserData;
165 
166  return ma_libopus_get_data_format(pOpus, NULL, NULL, NULL, pChannelMap, channelMapCap);
167 }
168 
170 {
173  NULL, /* onInitFileW() */
174  NULL, /* onInitMemory() */
177 };
178 
179 
180 
181 
182 void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount)
183 {
184  ma_data_source* pDataSource = (ma_data_source*)pDevice->pUserData;
185  if (pDataSource == NULL) {
186  return;
187  }
188 
189  ma_data_source_read_pcm_frames(pDataSource, pOutput, frameCount, NULL, MA_TRUE);
190 
191  (void)pInput;
192 }
193 
194 int main(int argc, char** argv)
195 {
196  ma_result result;
197  ma_decoder_config decoderConfig;
199  ma_device_config deviceConfig;
201  ma_format format;
202  ma_uint32 channels;
203  ma_uint32 sampleRate;
204 
205  /*
206  Add your custom backend vtables here. The order in the array defines the order of priority. The
207  vtables will be passed in via the decoder config.
208  */
209  ma_decoding_backend_vtable* pCustomBackendVTables[] =
210  {
213  };
214 
215 
216  if (argc < 2) {
217  printf("No input file.\n");
218  return -1;
219  }
220 
221 
222  /* Initialize the decoder. */
223  decoderConfig = ma_decoder_config_init_default();
224  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. */
225  decoderConfig.ppCustomBackendVTables = pCustomBackendVTables;
226  decoderConfig.customBackendCount = sizeof(pCustomBackendVTables) / sizeof(pCustomBackendVTables[0]);
227 
228  result = ma_decoder_init_file(argv[1], &decoderConfig, &decoder);
229  if (result != MA_SUCCESS) {
230  printf("Failed to initialize decoder.");
231  return -1;
232  }
233 
234 
235  /* Initialize the device. */
236  result = ma_data_source_get_data_format(&decoder, &format, &channels, &sampleRate);
237  if (result != MA_SUCCESS) {
238  printf("Failed to retrieve decoder data format.");
240  return -1;
241  }
242 
244  deviceConfig.playback.format = format;
245  deviceConfig.playback.channels = channels;
246  deviceConfig.sampleRate = sampleRate;
247  deviceConfig.dataCallback = data_callback;
248  deviceConfig.pUserData = &decoder;
249 
250  if (ma_device_init(NULL, &deviceConfig, &device) != MA_SUCCESS) {
251  printf("Failed to open playback device.\n");
253  return -1;
254  }
255 
256  if (ma_device_start(&device) != MA_SUCCESS) {
257  printf("Failed to start playback device.\n");
260  return -1;
261  }
262 
263  printf("Press Enter to quit...");
264  getchar();
265 
268 
269  return 0;
270 }
ma_libopus_init
MA_API ma_result ma_libopus_init(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_libopus *pOpus)
g_ma_decoding_backend_vtable_libopus
static ma_decoding_backend_vtable g_ma_decoding_backend_vtable_libopus
Definition: pvrecorder/src/miniaudio/examples/custom_decoder.c:169
ma_device_uninit
void ma_device_uninit(ma_device *pDevice)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:27425
ma_decoding_backend_get_channel_map__libopus
static ma_result ma_decoding_backend_get_channel_map__libopus(void *pUserData, ma_data_source *pBackend, ma_channel *pChannelMap, size_t channelMapCap)
Definition: pvrecorder/src/miniaudio/examples/custom_decoder.c:160
ma_device_start
ma_result ma_device_start(ma_device *pDevice)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:27485
ma_tell_proc
ma_result(* ma_tell_proc)(void *pUserData, ma_int64 *pCursor)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4682
NULL
#define NULL
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/extras/speex_resampler/thirdparty/resample.c:92
ma_decoding_backend_vtable
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4723
ma_libvorbis_get_data_format
MA_API ma_result ma_libvorbis_get_data_format(ma_libvorbis *pVorbis, ma_format *pFormat, ma_uint32 *pChannels, ma_uint32 *pSampleRate, ma_channel *pChannelMap, size_t channelMapCap)
ma_decoder_uninit
ma_result ma_decoder_uninit(ma_decoder *pDecoder)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:44739
ma_decoder_config
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5170
ma_data_source_read_pcm_frames
MA_API ma_result ma_data_source_read_pcm_frames(ma_data_source *pDataSource, void *pFramesOut, ma_uint64 frameCount, ma_uint64 *pFramesRead, ma_bool32 loop)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:37348
ma_decoding_backend_init__libopus
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)
Definition: pvrecorder/src/miniaudio/examples/custom_decoder.c:104
ma_libvorbis
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_libvorbis.h:21
ma_decoding_backend_init__libvorbis
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)
Definition: pvrecorder/src/miniaudio/examples/custom_decoder.c:27
decoder
ma_decoder decoder
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/tests/test_deviceio/ma_test_deviceio.c:61
ma_data_source
void ma_data_source
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4500
ma_format
ma_format
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1779
ma_decoding_backend_config
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4715
ma_device_type_playback
@ ma_device_type_playback
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3012
ma_allocation_callbacks
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1823
ma_device_config::dataCallback
ma_device_callback_proc dataCallback
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3110
g_ma_decoding_backend_vtable_libvorbis
static ma_decoding_backend_vtable g_ma_decoding_backend_vtable_libvorbis
Definition: pvrecorder/src/miniaudio/examples/custom_decoder.c:92
device
ma_device device
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/tests/test_deviceio/ma_test_deviceio.c:57
ma_decoding_backend_get_channel_map__libvorbis
static ma_result ma_decoding_backend_get_channel_map__libvorbis(void *pUserData, ma_data_source *pBackend, ma_channel *pChannelMap, size_t channelMapCap)
Definition: pvrecorder/src/miniaudio/examples/custom_decoder.c:83
ma_libvorbis_init_file
MA_API ma_result ma_libvorbis_init_file(const char *pFilePath, const ma_decoding_backend_config *pConfig, const ma_allocation_callbacks *pAllocationCallbacks, ma_libvorbis *pVorbis)
ma_libvorbis_init
MA_API ma_result ma_libvorbis_init(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_libvorbis *pVorbis)
ma_result
int ma_result
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1658
ma_decoder_config::ppCustomBackendVTables
ma_decoding_backend_vtable ** ppCustomBackendVTables
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4761
ma_libopus_uninit
MA_API void ma_libopus_uninit(ma_libopus *pOpus, const ma_allocation_callbacks *pAllocationCallbacks)
ma_libopus
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_libopus.h:20
ma_device::pUserData
void * pUserData
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3592
data_callback
void data_callback(ma_device *pDevice, void *pOutput, const void *pInput, ma_uint32 frameCount)
Definition: pvrecorder/src/miniaudio/examples/custom_decoder.c:182
main
int main(int argc, char **argv)
Definition: pvrecorder/src/miniaudio/examples/custom_decoder.c:194
ma_decoder_config::customBackendCount
ma_uint32 customBackendCount
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4762
ma_decoder_config_init_default
MA_API ma_decoder_config ma_decoder_config_init_default()
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:40663
ma_libopus_init_file
MA_API ma_result ma_libopus_init_file(const char *pFilePath, const ma_decoding_backend_config *pConfig, const ma_allocation_callbacks *pAllocationCallbacks, ma_libopus *pOpus)
ma_decoder
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5193
ma_libopus_get_data_format
MA_API ma_result ma_libopus_get_data_format(ma_libopus *pOpus, ma_format *pFormat, ma_uint32 *pChannels, ma_uint32 *pSampleRate, ma_channel *pChannelMap, size_t channelMapCap)
ma_read_proc
ma_result(* ma_read_proc)(void *pUserData, void *pBufferOut, size_t bytesToRead, size_t *pBytesRead)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4680
ma_decoding_backend_uninit__libvorbis
static void ma_decoding_backend_uninit__libvorbis(void *pUserData, ma_data_source *pBackend, const ma_allocation_callbacks *pAllocationCallbacks)
Definition: pvrecorder/src/miniaudio/examples/custom_decoder.c:73
ma_uint32
uint32_t ma_uint32
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1503
ma_device_config::format
ma_format format
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3128
ma_device_config_init
ma_device_config ma_device_config_init(ma_device_type deviceType)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:27034
ma_seek_proc
ma_result(* ma_seek_proc)(void *pUserData, ma_int64 offset, ma_seek_origin origin)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4681
ma_device_config::channels
ma_uint32 channels
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3129
ma_libvorbis_uninit
MA_API void ma_libvorbis_uninit(ma_libvorbis *pVorbis, const ma_allocation_callbacks *pAllocationCallbacks)
ma_decoder_init_file
ma_result ma_decoder_init_file(const char *pFilePath, const ma_decoder_config *pConfig, ma_decoder *pDecoder)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:44687
python.test_porcupine.argv
argv
Definition: test_porcupine.py:158
ma_device_init
ma_result ma_device_init(ma_context *pContext, const ma_device_config *pConfig, ma_device *pDevice)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:27048
ma_device
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3584
ma_device_config
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3100
ma_device_config::sampleRate
ma_uint32 sampleRate
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3103
ma_decoding_backend_init_file__libvorbis
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)
Definition: pvrecorder/src/miniaudio/examples/custom_decoder.c:50
MA_TRUE
#define MA_TRUE
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1530
ma_decoding_backend_uninit__libopus
static void ma_decoding_backend_uninit__libopus(void *pUserData, ma_data_source *pBackend, const ma_allocation_callbacks *pAllocationCallbacks)
Definition: pvrecorder/src/miniaudio/examples/custom_decoder.c:150
MA_SUCCESS
#define MA_SUCCESS
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1659
ma_decoder_config::pCustomBackendUserData
void * pCustomBackendUserData
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:4763
ma_data_source_get_data_format
MA_API ma_result ma_data_source_get_data_format(ma_data_source *pDataSource, ma_format *pFormat, ma_uint32 *pChannels, ma_uint32 *pSampleRate)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:37609
ma_decoding_backend_init_file__libopus
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)
Definition: pvrecorder/src/miniaudio/examples/custom_decoder.c:127
ma_malloc
void * ma_malloc(size_t sz, const ma_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:37117
ma_channel
ma_uint8 ma_channel
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1600
ma_device_config::playback
struct ma_device_config::@97 playback
ma_free
void ma_free(void *p, const ma_allocation_callbacks *pAllocationCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:37139
ma_device_config::pUserData
void * pUserData
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3112
MA_OUT_OF_MEMORY
#define MA_OUT_OF_MEMORY
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1663


picovoice_driver
Author(s):
autogenerated on Fri Apr 1 2022 02:13:48