pvrecorder/src/miniaudio/examples/custom_backend.c
Go to the documentation of this file.
1 /*
2 This example show how a custom backend can be implemented.
3 
4 This implements a full-featured SDL2 backend. It's intentionally built using the same paradigms as the built-in backends in order to make
5 it suitable as a solid basis for a custom implementation. The SDL2 backend can be disabled with MA_NO_SDL, exactly like the build-in
6 backends. It supports both runtime and compile-time linking and respects the MA_NO_RUNTIME_LINKING option. It also works on Emscripten
7 which requires the `-s USE_SDL=2` option.
8 
9 There may be times where you want to support more than one custom backend. This example has been designed to make it easy to plug-in extra
10 custom backends without needing to modify any of the base miniaudio initialization code. A custom context structure is declared called
11 `ma_context_ex`. The first member of this structure is a `ma_context` object which allows it to be cast between the two. The same is done
12 for devices, which is called `ma_device_ex`. In these structures there is a section for each custom backend, which in this example is just
13 SDL. These are only enabled at compile time if `MA_SUPPORT_SDL` is defined, which it always is in this example (you may want to have some
14 logic which more intelligently enables or disables SDL support).
15 
16 To use a custom backend, at a minimum you must set the `custom.onContextInit()` callback in the context config. You do not need to set the
17 other callbacks, but if you don't, you must set them in the implementation of the `onContextInit()` callback which is done via an output
18 parameter. This is the approach taken by this example because it's the simplest way to support multiple custom backends. The idea is that
19 the `onContextInit()` callback is set to a generic "loader", which then calls out to a backend-specific implementation which then sets the
20 remaining callbacks if it is successfully initialized.
21 
22 Custom backends are identified with the `ma_backend_custom` backend type. For the purpose of demonstration, this example only uses the
23 `ma_backend_custom` backend type because otherwise the built-in backends would always get chosen first and none of the code for the custom
24 backends would actually get hit. By default, the `ma_backend_custom` backend is the lowest priority backend, except for `ma_backend_null`.
25 */
26 #define MINIAUDIO_IMPLEMENTATION
27 #include "../miniaudio.h"
28 
29 #ifdef __EMSCRIPTEN__
30 #include <emscripten.h>
31 
32 void main_loop__em()
33 {
34 }
35 #endif
36 
37 /* Support SDL on everything. */
38 #define MA_SUPPORT_SDL
39 
40 /*
41 Only enable SDL if it's hasn't been explicitly disabled (MA_NO_SDL) or enabled (MA_ENABLE_SDL with
42 MA_ENABLE_ONLY_SPECIFIC_BACKENDS) and it's supported at compile time (MA_SUPPORT_SDL).
43 */
44 #if defined(MA_SUPPORT_SDL) && !defined(MA_NO_SDL) && (!defined(MA_ENABLE_ONLY_SPECIFIC_BACKENDS) || defined(MA_ENABLE_SDL))
45  #define MA_HAS_SDL
46 #endif
47 
48 
49 typedef struct
50 {
51  ma_context context; /* Make this the first member so we can cast between ma_context and ma_context_ex. */
52 #if defined(MA_SUPPORT_SDL)
53  struct
54  {
55  ma_handle hSDL; /* A handle to the SDL2 shared object. We dynamically load function pointers at runtime so we can avoid linking. */
56  ma_proc SDL_InitSubSystem;
57  ma_proc SDL_QuitSubSystem;
58  ma_proc SDL_GetNumAudioDevices;
59  ma_proc SDL_GetAudioDeviceName;
60  ma_proc SDL_CloseAudioDevice;
61  ma_proc SDL_OpenAudioDevice;
62  ma_proc SDL_PauseAudioDevice;
63  } sdl;
64 #endif
66 
67 typedef struct
68 {
69  ma_device device; /* Make this the first member so we can cast between ma_device and ma_device_ex. */
70 #if defined(MA_SUPPORT_SDL)
71  struct
72  {
73  int deviceIDPlayback;
74  int deviceIDCapture;
75  } sdl;
76 #endif
77 } ma_device_ex;
78 
79 
80 
81 #if defined(MA_HAS_SDL)
82  /* SDL headers are necessary if using compile-time linking. */
83  #ifdef MA_NO_RUNTIME_LINKING
84  #ifdef __has_include
85  #ifdef MA_EMSCRIPTEN
86  #if !__has_include(<SDL/SDL_audio.h>)
87  #undef MA_HAS_SDL
88  #endif
89  #else
90  #if !__has_include(<SDL2/SDL_audio.h>)
91  #undef MA_HAS_SDL
92  #endif
93  #endif
94  #endif
95  #endif
96 #endif
97 
98 
99 #if defined(MA_HAS_SDL)
100 #define MA_SDL_INIT_AUDIO 0x00000010
101 #define MA_AUDIO_U8 0x0008
102 #define MA_AUDIO_S16 0x8010
103 #define MA_AUDIO_S32 0x8020
104 #define MA_AUDIO_F32 0x8120
105 #define MA_SDL_AUDIO_ALLOW_FREQUENCY_CHANGE 0x00000001
106 #define MA_SDL_AUDIO_ALLOW_FORMAT_CHANGE 0x00000002
107 #define MA_SDL_AUDIO_ALLOW_CHANNELS_CHANGE 0x00000004
108 #define MA_SDL_AUDIO_ALLOW_ANY_CHANGE (MA_SDL_AUDIO_ALLOW_FREQUENCY_CHANGE | MA_SDL_AUDIO_ALLOW_FORMAT_CHANGE | MA_SDL_AUDIO_ALLOW_CHANNELS_CHANGE)
109 
110 /* If we are linking at compile time we'll just #include SDL.h. Otherwise we can just redeclare some stuff to avoid the need for development packages to be installed. */
111 #ifdef MA_NO_RUNTIME_LINKING
112  #define SDL_MAIN_HANDLED
113  #ifdef MA_EMSCRIPTEN
114  #include <SDL/SDL.h>
115  #else
116  #include <SDL2/SDL.h>
117  #endif
118 
119  typedef SDL_AudioCallback MA_SDL_AudioCallback;
120  typedef SDL_AudioSpec MA_SDL_AudioSpec;
121  typedef SDL_AudioFormat MA_SDL_AudioFormat;
122  typedef SDL_AudioDeviceID MA_SDL_AudioDeviceID;
123 #else
124  typedef void (* MA_SDL_AudioCallback)(void* userdata, ma_uint8* stream, int len);
127 
128  typedef struct MA_SDL_AudioSpec
129  {
130  int freq;
136  ma_uint32 size;
138  void* userdata;
140 #endif
141 
142 typedef int (* MA_PFN_SDL_InitSubSystem)(ma_uint32 flags);
143 typedef void (* MA_PFN_SDL_QuitSubSystem)(ma_uint32 flags);
144 typedef int (* MA_PFN_SDL_GetNumAudioDevices)(int iscapture);
145 typedef const char* (* MA_PFN_SDL_GetAudioDeviceName)(int index, int iscapture);
147 typedef MA_SDL_AudioDeviceID (* MA_PFN_SDL_OpenAudioDevice)(const char* device, int iscapture, const MA_SDL_AudioSpec* desired, MA_SDL_AudioSpec* obtained, int allowed_changes);
148 typedef void (* MA_PFN_SDL_PauseAudioDevice)(MA_SDL_AudioDeviceID dev, int pause_on);
149 
151 {
152  switch (format)
153  {
154  case ma_format_unknown: return 0;
155  case ma_format_u8: return MA_AUDIO_U8;
156  case ma_format_s16: return MA_AUDIO_S16;
157  case ma_format_s24: return MA_AUDIO_S32; /* Closest match. */
158  case ma_format_s32: return MA_AUDIO_S32;
159  case ma_format_f32: return MA_AUDIO_F32;
160  default: return 0;
161  }
162 }
163 
165 {
166  switch (format)
167  {
168  case MA_AUDIO_U8: return ma_format_u8;
169  case MA_AUDIO_S16: return ma_format_s16;
170  case MA_AUDIO_S32: return ma_format_s32;
171  case MA_AUDIO_F32: return ma_format_f32;
172  default: return ma_format_unknown;
173  }
174 }
175 
177 {
178  ma_context_ex* pContextEx = (ma_context_ex*)pContext;
179  ma_bool32 isTerminated = MA_FALSE;
180  ma_bool32 cbResult;
181  int iDevice;
182 
183  MA_ASSERT(pContext != NULL);
184  MA_ASSERT(callback != NULL);
185 
186  /* Playback */
187  if (!isTerminated) {
188  int deviceCount = ((MA_PFN_SDL_GetNumAudioDevices)pContextEx->sdl.SDL_GetNumAudioDevices)(0);
189  for (iDevice = 0; iDevice < deviceCount; ++iDevice) {
190  ma_device_info deviceInfo;
191  MA_ZERO_OBJECT(&deviceInfo);
192 
193  deviceInfo.id.custom.i = iDevice;
194  ma_strncpy_s(deviceInfo.name, sizeof(deviceInfo.name), ((MA_PFN_SDL_GetAudioDeviceName)pContextEx->sdl.SDL_GetAudioDeviceName)(iDevice, 0), (size_t)-1);
195 
196  if (iDevice == 0) {
197  deviceInfo.isDefault = MA_TRUE;
198  }
199 
200  cbResult = callback(pContext, ma_device_type_playback, &deviceInfo, pUserData);
201  if (cbResult == MA_FALSE) {
202  isTerminated = MA_TRUE;
203  break;
204  }
205  }
206  }
207 
208  /* Capture */
209  if (!isTerminated) {
210  int deviceCount = ((MA_PFN_SDL_GetNumAudioDevices)pContextEx->sdl.SDL_GetNumAudioDevices)(1);
211  for (iDevice = 0; iDevice < deviceCount; ++iDevice) {
212  ma_device_info deviceInfo;
213  MA_ZERO_OBJECT(&deviceInfo);
214 
215  deviceInfo.id.custom.i = iDevice;
216  ma_strncpy_s(deviceInfo.name, sizeof(deviceInfo.name), ((MA_PFN_SDL_GetAudioDeviceName)pContextEx->sdl.SDL_GetAudioDeviceName)(iDevice, 1), (size_t)-1);
217 
218  if (iDevice == 0) {
219  deviceInfo.isDefault = MA_TRUE;
220  }
221 
222  cbResult = callback(pContext, ma_device_type_capture, &deviceInfo, pUserData);
223  if (cbResult == MA_FALSE) {
224  isTerminated = MA_TRUE;
225  break;
226  }
227  }
228  }
229 
230  return MA_SUCCESS;
231 }
232 
233 static ma_result ma_context_get_device_info__sdl(ma_context* pContext, ma_device_type deviceType, const ma_device_id* pDeviceID, ma_device_info* pDeviceInfo)
234 {
235  ma_context_ex* pContextEx = (ma_context_ex*)pContext;
236 
237 #if !defined(__EMSCRIPTEN__)
238  MA_SDL_AudioSpec desiredSpec;
239  MA_SDL_AudioSpec obtainedSpec;
240  MA_SDL_AudioDeviceID tempDeviceID;
241  const char* pDeviceName;
242 #endif
243 
244  MA_ASSERT(pContext != NULL);
245 
246  if (pDeviceID == NULL) {
247  if (deviceType == ma_device_type_playback) {
248  pDeviceInfo->id.custom.i = 0;
249  ma_strncpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), MA_DEFAULT_PLAYBACK_DEVICE_NAME, (size_t)-1);
250  } else {
251  pDeviceInfo->id.custom.i = 0;
252  ma_strncpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), MA_DEFAULT_CAPTURE_DEVICE_NAME, (size_t)-1);
253  }
254  } else {
255  pDeviceInfo->id.custom.i = pDeviceID->custom.i;
256  ma_strncpy_s(pDeviceInfo->name, sizeof(pDeviceInfo->name), ((MA_PFN_SDL_GetAudioDeviceName)pContextEx->sdl.SDL_GetAudioDeviceName)(pDeviceID->custom.i, (deviceType == ma_device_type_playback) ? 0 : 1), (size_t)-1);
257  }
258 
259  if (pDeviceInfo->id.custom.i == 0) {
260  pDeviceInfo->isDefault = MA_TRUE;
261  }
262 
263  /*
264  To get an accurate idea on the backend's native format we need to open the device. Not ideal, but it's the only way. An
265  alternative to this is to report all channel counts, sample rates and formats, but that doesn't offer a good representation
266  of the device's _actual_ ideal format.
267 
268  Note: With Emscripten, it looks like non-zero values need to be specified for desiredSpec. Whatever is specified in
269  desiredSpec will be used by SDL since it uses it just does it's own format conversion internally. Therefore, from what
270  I can tell, there's no real way to know the device's actual format which means I'm just going to fall back to the full
271  range of channels and sample rates on Emscripten builds.
272  */
273 #if defined(__EMSCRIPTEN__)
274  /* Good practice to prioritize the best format first so that the application can use the first data format as their chosen one if desired. */
275  pDeviceInfo->nativeDataFormatCount = 3;
276  pDeviceInfo->nativeDataFormats[0].format = ma_format_s16;
277  pDeviceInfo->nativeDataFormats[0].channels = 0; /* All channel counts supported. */
278  pDeviceInfo->nativeDataFormats[0].sampleRate = 0; /* All sample rates supported. */
279  pDeviceInfo->nativeDataFormats[0].flags = 0;
280  pDeviceInfo->nativeDataFormats[1].format = ma_format_s32;
281  pDeviceInfo->nativeDataFormats[1].channels = 0; /* All channel counts supported. */
282  pDeviceInfo->nativeDataFormats[1].sampleRate = 0; /* All sample rates supported. */
283  pDeviceInfo->nativeDataFormats[1].flags = 0;
284  pDeviceInfo->nativeDataFormats[2].format = ma_format_u8;
285  pDeviceInfo->nativeDataFormats[2].channels = 0; /* All channel counts supported. */
286  pDeviceInfo->nativeDataFormats[2].sampleRate = 0; /* All sample rates supported. */
287  pDeviceInfo->nativeDataFormats[2].flags = 0;
288 #else
289  MA_ZERO_MEMORY(&desiredSpec, sizeof(desiredSpec));
290 
291  pDeviceName = NULL;
292  if (pDeviceID != NULL) {
293  pDeviceName = ((MA_PFN_SDL_GetAudioDeviceName)pContextEx->sdl.SDL_GetAudioDeviceName)(pDeviceID->custom.i, (deviceType == ma_device_type_playback) ? 0 : 1);
294  }
295 
296  tempDeviceID = ((MA_PFN_SDL_OpenAudioDevice)pContextEx->sdl.SDL_OpenAudioDevice)(pDeviceName, (deviceType == ma_device_type_playback) ? 0 : 1, &desiredSpec, &obtainedSpec, MA_SDL_AUDIO_ALLOW_ANY_CHANGE);
297  if (tempDeviceID == 0) {
298  return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "Failed to open SDL device.", MA_FAILED_TO_OPEN_BACKEND_DEVICE);
299  }
300 
301  ((MA_PFN_SDL_CloseAudioDevice)pContextEx->sdl.SDL_CloseAudioDevice)(tempDeviceID);
302 
303  /* Only reporting a single native data format. It'll be whatever SDL decides is the best. */
304  pDeviceInfo->nativeDataFormatCount = 1;
305  pDeviceInfo->nativeDataFormats[0].format = ma_format_from_sdl(obtainedSpec.format);
306  pDeviceInfo->nativeDataFormats[0].channels = obtainedSpec.channels;
307  pDeviceInfo->nativeDataFormats[0].sampleRate = obtainedSpec.freq;
308  pDeviceInfo->nativeDataFormats[0].flags = 0;
309 
310  /* If miniaudio does not support the format, just use f32 as the native format (SDL will do the necessary conversions for us). */
311  if (pDeviceInfo->nativeDataFormats[0].format == ma_format_unknown) {
312  pDeviceInfo->nativeDataFormats[0].format = ma_format_f32;
313  }
314 #endif /* __EMSCRIPTEN__ */
315 
316  return MA_SUCCESS;
317 }
318 
319 
320 void ma_audio_callback_capture__sdl(void* pUserData, ma_uint8* pBuffer, int bufferSizeInBytes)
321 {
322  ma_device_ex* pDeviceEx = (ma_device_ex*)pUserData;
323 
324  MA_ASSERT(pDeviceEx != NULL);
325 
326  ma_device_handle_backend_data_callback((ma_device*)pDeviceEx, NULL, pBuffer, (ma_uint32)bufferSizeInBytes / ma_get_bytes_per_frame(pDeviceEx->device.capture.internalFormat, pDeviceEx->device.capture.internalChannels));
327 }
328 
329 void ma_audio_callback_playback__sdl(void* pUserData, ma_uint8* pBuffer, int bufferSizeInBytes)
330 {
331  ma_device_ex* pDeviceEx = (ma_device_ex*)pUserData;
332 
333  MA_ASSERT(pDeviceEx != NULL);
334 
335  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));
336 }
337 
339 {
340  ma_context_ex* pContextEx = (ma_context_ex*)pDeviceEx->device.pContext;
341  MA_SDL_AudioSpec desiredSpec;
342  MA_SDL_AudioSpec obtainedSpec;
343  const char* pDeviceName;
344  int deviceID;
345 
346  MA_ASSERT(pDeviceEx != NULL);
347  MA_ASSERT(pDescriptor != NULL);
348 
349  /*
350  SDL is a little bit awkward with specifying the buffer size, You need to specify the size of the buffer in frames, but since we may
351  have requested a period size in milliseconds we'll need to convert, which depends on the sample rate. But there's a possibility that
352  the sample rate just set to 0, which indicates that the native sample rate should be used. There's no practical way to calculate this
353  that I can think of right now so I'm just using MA_DEFAULT_SAMPLE_RATE.
354  */
355  if (pDescriptor->sampleRate == 0) {
356  pDescriptor->sampleRate = MA_DEFAULT_SAMPLE_RATE;
357  }
358 
359  /*
360  When determining the period size, you need to take defaults into account. This is how the size of the period should be determined.
361 
362  1) If periodSizeInFrames is not 0, use periodSizeInFrames; else
363  2) If periodSizeInMilliseconds is not 0, use periodSizeInMilliseconds; else
364  3) If both periodSizeInFrames and periodSizeInMilliseconds is 0, use the backend's default. If the backend does not allow a default
365  buffer size, use a default value of MA_DEFAULT_PERIOD_SIZE_IN_MILLISECONDS_LOW_LATENCY or
366  MA_DEFAULT_PERIOD_SIZE_IN_MILLISECONDS_CONSERVATIVE depending on the value of pConfig->performanceProfile.
367 
368  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
369  calculation of the period size as accurate as possible, but sometimes it's just not practical so just use whatever you can.
370 
371  A helper function called ma_calculate_buffer_size_in_frames_from_descriptor() is available to do all of this for you which is what
372  we'll be using here.
373  */
375 
376  /* SDL wants the buffer size to be a power of 2 for some reason. */
377  if (pDescriptor->periodSizeInFrames > 32768) {
378  pDescriptor->periodSizeInFrames = 32768;
379  } else {
380  pDescriptor->periodSizeInFrames = ma_next_power_of_2(pDescriptor->periodSizeInFrames);
381  }
382 
383 
384  /* We now have enough information to set up the device. */
385  MA_ZERO_OBJECT(&desiredSpec);
386  desiredSpec.freq = (int)pDescriptor->sampleRate;
387  desiredSpec.format = ma_format_to_sdl(pDescriptor->format);
388  desiredSpec.channels = (ma_uint8)pDescriptor->channels;
389  desiredSpec.samples = (ma_uint16)pDescriptor->periodSizeInFrames;
391  desiredSpec.userdata = pDeviceEx;
392 
393  /* We'll fall back to f32 if we don't have an appropriate mapping between SDL and miniaudio. */
394  if (desiredSpec.format == 0) {
395  desiredSpec.format = MA_AUDIO_F32;
396  }
397 
398  pDeviceName = NULL;
399  if (pDescriptor->pDeviceID != NULL) {
400  pDeviceName = ((MA_PFN_SDL_GetAudioDeviceName)pContextEx->sdl.SDL_GetAudioDeviceName)(pDescriptor->pDeviceID->custom.i, (pConfig->deviceType == ma_device_type_playback) ? 0 : 1);
401  }
402 
403  deviceID = ((MA_PFN_SDL_OpenAudioDevice)pContextEx->sdl.SDL_OpenAudioDevice)(pDeviceName, (pConfig->deviceType == ma_device_type_playback) ? 0 : 1, &desiredSpec, &obtainedSpec, MA_SDL_AUDIO_ALLOW_ANY_CHANGE);
404  if (deviceID == 0) {
405  return ma_post_error((ma_device*)pDeviceEx, MA_LOG_LEVEL_ERROR, "Failed to open SDL2 device.", MA_FAILED_TO_OPEN_BACKEND_DEVICE);
406  }
407 
408  if (pConfig->deviceType == ma_device_type_playback) {
409  pDeviceEx->sdl.deviceIDPlayback = deviceID;
410  } else {
411  pDeviceEx->sdl.deviceIDCapture = deviceID;
412  }
413 
414  /* The descriptor needs to be updated with our actual settings. */
415  pDescriptor->format = ma_format_from_sdl(obtainedSpec.format);
416  pDescriptor->channels = obtainedSpec.channels;
417  pDescriptor->sampleRate = (ma_uint32)obtainedSpec.freq;
419  pDescriptor->periodSizeInFrames = obtainedSpec.samples;
420  pDescriptor->periodCount = 1; /* SDL doesn't use the notion of period counts, so just set to 1. */
421 
422  return MA_SUCCESS;
423 }
424 
425 static ma_result ma_device_init__sdl(ma_device* pDevice, const ma_device_config* pConfig, ma_device_descriptor* pDescriptorPlayback, ma_device_descriptor* pDescriptorCapture)
426 {
427  ma_device_ex* pDeviceEx = (ma_device_ex*)pDevice;
428  ma_context_ex* pContextEx = (ma_context_ex*)pDevice->pContext;
429  ma_result result;
430 
431  MA_ASSERT(pDevice != NULL);
432 
433  /* SDL does not support loopback mode, so must return MA_DEVICE_TYPE_NOT_SUPPORTED if it's requested. */
434  if (pConfig->deviceType == ma_device_type_loopback) {
436  }
437 
438  if (pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) {
439  result = ma_device_init_internal__sdl(pDeviceEx, pConfig, pDescriptorCapture);
440  if (result != MA_SUCCESS) {
441  return result;
442  }
443  }
444 
445  if (pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) {
446  result = ma_device_init_internal__sdl(pDeviceEx, pConfig, pDescriptorPlayback);
447  if (result != MA_SUCCESS) {
448  if (pConfig->deviceType == ma_device_type_duplex) {
450  }
451 
452  return result;
453  }
454  }
455 
456  return MA_SUCCESS;
457 }
458 
460 {
461  ma_device_ex* pDeviceEx = (ma_device_ex*)pDevice;
462  ma_context_ex* pContextEx = (ma_context_ex*)pDevice->pContext;
463 
464  MA_ASSERT(pDevice != NULL);
465 
466  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
468  }
469 
470  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
472  }
473 
474  return MA_SUCCESS;
475 }
476 
478 {
479  ma_device_ex* pDeviceEx = (ma_device_ex*)pDevice;
480  ma_context_ex* pContextEx = (ma_context_ex*)pDevice->pContext;
481 
482  MA_ASSERT(pDevice != NULL);
483 
484  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
486  }
487 
488  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
490  }
491 
492  return MA_SUCCESS;
493 }
494 
496 {
497  ma_device_ex* pDeviceEx = (ma_device_ex*)pDevice;
498  ma_context_ex* pContextEx = (ma_context_ex*)pDevice->pContext;
499 
500  MA_ASSERT(pDevice != NULL);
501 
502  if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
504  }
505 
506  if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
508  }
509 
510  return MA_SUCCESS;
511 }
512 
514 {
515  ma_context_ex* pContextEx = (ma_context_ex*)pContext;
516 
517  MA_ASSERT(pContext != NULL);
518 
520 
521  /* Close the handle to the SDL shared object last. */
522  ma_dlclose(pContext, pContextEx->sdl.hSDL);
523  pContextEx->sdl.hSDL = NULL;
524 
525  return MA_SUCCESS;
526 }
527 
529 {
530  ma_context_ex* pContextEx = (ma_context_ex*)pContext;
531  int resultSDL;
532 
533 #ifndef MA_NO_RUNTIME_LINKING
534  /* We'll use a list of possible shared object names for easier extensibility. */
535  size_t iName;
536  const char* pSDLNames[] = {
537 #if defined(_WIN32)
538  "SDL2.dll"
539 #elif defined(__APPLE__)
540  "SDL2.framework/SDL2"
541 #else
542  "libSDL2-2.0.so.0"
543 #endif
544  };
545 
546  MA_ASSERT(pContext != NULL);
547 
548  (void)pConfig;
549 
550  /* Check if we have SDL2 installed somewhere. If not it's not usable and we need to abort. */
551  for (iName = 0; iName < ma_countof(pSDLNames); iName += 1) {
552  pContextEx->sdl.hSDL = ma_dlopen(pContext, pSDLNames[iName]);
553  if (pContextEx->sdl.hSDL != NULL) {
554  break;
555  }
556  }
557 
558  if (pContextEx->sdl.hSDL == NULL) {
559  return MA_NO_BACKEND; /* SDL2 could not be loaded. */
560  }
561 
562  /* Now that we have the handle to the shared object we can go ahead and load some function pointers. */
563  pContextEx->sdl.SDL_InitSubSystem = ma_dlsym(pContext, pContextEx->sdl.hSDL, "SDL_InitSubSystem");
564  pContextEx->sdl.SDL_QuitSubSystem = ma_dlsym(pContext, pContextEx->sdl.hSDL, "SDL_QuitSubSystem");
565  pContextEx->sdl.SDL_GetNumAudioDevices = ma_dlsym(pContext, pContextEx->sdl.hSDL, "SDL_GetNumAudioDevices");
566  pContextEx->sdl.SDL_GetAudioDeviceName = ma_dlsym(pContext, pContextEx->sdl.hSDL, "SDL_GetAudioDeviceName");
567  pContextEx->sdl.SDL_CloseAudioDevice = ma_dlsym(pContext, pContextEx->sdl.hSDL, "SDL_CloseAudioDevice");
568  pContextEx->sdl.SDL_OpenAudioDevice = ma_dlsym(pContext, pContextEx->sdl.hSDL, "SDL_OpenAudioDevice");
569  pContextEx->sdl.SDL_PauseAudioDevice = ma_dlsym(pContext, pContextEx->sdl.hSDL, "SDL_PauseAudioDevice");
570 #else
571  pContextEx->sdl.SDL_InitSubSystem = (ma_proc)SDL_InitSubSystem;
572  pContextEx->sdl.SDL_QuitSubSystem = (ma_proc)SDL_QuitSubSystem;
573  pContextEx->sdl.SDL_GetNumAudioDevices = (ma_proc)SDL_GetNumAudioDevices;
574  pContextEx->sdl.SDL_GetAudioDeviceName = (ma_proc)SDL_GetAudioDeviceName;
575  pContextEx->sdl.SDL_CloseAudioDevice = (ma_proc)SDL_CloseAudioDevice;
576  pContextEx->sdl.SDL_OpenAudioDevice = (ma_proc)SDL_OpenAudioDevice;
577  pContextEx->sdl.SDL_PauseAudioDevice = (ma_proc)SDL_PauseAudioDevice;
578 #endif /* MA_NO_RUNTIME_LINKING */
579 
581  if (resultSDL != 0) {
582  ma_dlclose(pContext, pContextEx->sdl.hSDL);
583  return MA_ERROR;
584  }
585 
586  /*
587  The last step is to make sure the callbacks are set properly in `pCallbacks`. Internally, miniaudio will copy these callbacks into the
588  context object and then use them for then on for calling into our custom backend.
589  */
590  pCallbacks->onContextInit = ma_context_init__sdl;
594  pCallbacks->onDeviceInit = ma_device_init__sdl;
596  pCallbacks->onDeviceStart = ma_device_start__sdl;
597  pCallbacks->onDeviceStop = ma_device_stop__sdl;
598 
599  return MA_SUCCESS;
600 }
601 #endif /* MA_HAS_SDL */
602 
603 
604 /*
605 This is our custom backend "loader". All this does is attempts to initialize our custom backends in the order they are listed. The first
606 one to successfully initialize is the one that's chosen. In this example we're just listing them statically, but you can use whatever logic
607 you want to handle backend selection.
608 
609 This is used as the onContextInit() callback in the context config.
610 */
612 {
613  ma_result result = MA_NO_BACKEND;
614 
615  /* Silence some unused parameter warnings just in case no custom backends are enabled. */
616  (void)pContext;
617  (void)pCallbacks;
618 
619  /* SDL. */
620 #if !defined(MA_NO_SDL)
621  if (result != MA_SUCCESS) {
622  result = ma_context_init__sdl(pContext, pConfig, pCallbacks);
623  }
624 #endif
625 
626  /* ... plug in any other custom backends here ... */
627 
628  /* If we have a success result we have initialized a backend. Otherwise we need to tell miniaudio about the error so it can skip over our custom backends. */
629  return result;
630 }
631 
632 
633 /*
634 Main program starts here.
635 */
636 #define DEVICE_FORMAT ma_format_f32
637 #define DEVICE_CHANNELS 2
638 #define DEVICE_SAMPLE_RATE 48000
639 
640 void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount)
641 {
643 
644  if (pDevice->type == ma_device_type_playback) {
645  ma_waveform* pSineWave;
646 
647  pSineWave = (ma_waveform*)pDevice->pUserData;
648  MA_ASSERT(pSineWave != NULL);
649 
650  ma_waveform_read_pcm_frames(pSineWave, pOutput, frameCount);
651  }
652 
653  if (pDevice->type == ma_device_type_duplex) {
654  ma_copy_pcm_frames(pOutput, pInput, frameCount, pDevice->playback.format, pDevice->playback.channels);
655  }
656 }
657 
658 int main(int argc, char** argv)
659 {
660  ma_result result;
661  ma_context_config contextConfig;
663  ma_device_config deviceConfig;
665  ma_waveform_config sineWaveConfig;
666  ma_waveform sineWave;
667 
668  /*
669  We're just using ma_backend_custom in this example for demonstration purposes, but a more realistic use case would probably want to include
670  other backends as well for robustness.
671  */
672  ma_backend backends[] = {
674  };
675 
676  /*
677  To implement a custom backend you need to implement the callbacks in the "custom" member of the context config. The only mandatory
678  callback required at this point is the onContextInit() callback. If you do not set the other callbacks, you must set them in
679  onContextInit() by setting them on the `pCallbacks` parameter.
680 
681  The way we're doing it in this example enables us to easily plug in multiple custom backends. What we do is set the onContextInit()
682  callback to a generic "loader" function (ma_context_init__custom_loader() in this example), which then calls out to backend-specific
683  context initialization routines, one of which will be for SDL. That way, if for example we wanted to add support for another backend,
684  we don't need to touch this part of the code. Instead we add logic to ma_context_init__custom_loader() to choose the most appropriate
685  custom backend. That will then fill out the other callbacks appropriately.
686  */
687  contextConfig = ma_context_config_init();
689 
690  result = ma_context_init(backends, sizeof(backends)/sizeof(backends[0]), &contextConfig, (ma_context*)&context);
691  if (result != MA_SUCCESS) {
692  return -1;
693  }
694 
695  /* In playback mode we're just going to play a sine wave. */
697  ma_waveform_init(&sineWaveConfig, &sineWave);
698 
699  /* The device is created exactly as per normal. */
701  deviceConfig.playback.format = DEVICE_FORMAT;
702  deviceConfig.playback.channels = DEVICE_CHANNELS;
703  deviceConfig.capture.format = DEVICE_FORMAT;
704  deviceConfig.capture.channels = DEVICE_CHANNELS;
705  deviceConfig.sampleRate = DEVICE_SAMPLE_RATE;
706  deviceConfig.dataCallback = data_callback;
707  deviceConfig.pUserData = &sineWave;
708 
709  result = ma_device_init((ma_context*)&context, &deviceConfig, (ma_device*)&device);
710  if (result != MA_SUCCESS) {
712  return -1;
713  }
714 
715 
716  printf("Device Name: %s\n", ((ma_device*)&device)->playback.name);
717 
721  return -5;
722  }
723 
724 #ifdef __EMSCRIPTEN__
725  emscripten_set_main_loop(main_loop__em, 0, 1);
726 #else
727  printf("Press Enter to quit...\n");
728  getchar();
729 #endif
730 
733 
734  (void)argc;
735  (void)argv;
736 
737  return 0;
738 }
ma_get_bytes_per_frame
static MA_INLINE ma_uint32 ma_get_bytes_per_frame(ma_format format, ma_uint32 channels)
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2673
ma_device_ex::deviceIDCapture
int deviceIDCapture
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/examples/custom_backend.c:74
ma_strncpy_s
MA_API int ma_strncpy_s(char *dst, size_t dstSizeInBytes, const char *src, size_t count)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:925
MA_FALSE
#define MA_FALSE
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1531
ma_device_type_loopback
@ ma_device_type_loopback
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3015
MA_DEVICE_TYPE_NOT_SUPPORTED
#define MA_DEVICE_TYPE_NOT_SUPPORTED
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1716
ma_format_from_sdl
ma_format ma_format_from_sdl(MA_SDL_AudioFormat format)
Definition: pvrecorder/src/miniaudio/examples/custom_backend.c:164
MA_SDL_AudioSpec::samples
ma_uint16 samples
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/examples/custom_backend.c:134
MA_PFN_SDL_GetAudioDeviceName
const typedef char *(* MA_PFN_SDL_GetAudioDeviceName)(int index, int iscapture)
Definition: pvrecorder/src/miniaudio/examples/custom_backend.c:145
ma_context_get_device_info__sdl
static ma_result ma_context_get_device_info__sdl(ma_context *pContext, ma_device_type deviceType, const ma_device_id *pDeviceID, ma_device_info *pDeviceInfo)
Definition: pvrecorder/src/miniaudio/examples/custom_backend.c:233
ma_uint8
uint8_t ma_uint8
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1499
ma_device_uninit
void ma_device_uninit(ma_device *pDevice)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:27425
ma_dlsym
MA_API ma_proc ma_dlsym(ma_context *pContext, ma_handle handle, const char *symbol)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:5625
MA_SDL_AudioSpec
struct MA_SDL_AudioSpec MA_SDL_AudioSpec
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_device::internalChannels
ma_uint32 internalChannels
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3629
context
ma_context context
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/tests/test_deviceio/ma_test_deviceio.c:56
NULL
#define NULL
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/extras/speex_resampler/thirdparty/resample.c:92
ma_proc
void(* ma_proc)(void)
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1535
DEVICE_SAMPLE_RATE
#define DEVICE_SAMPLE_RATE
Definition: pvrecorder/src/miniaudio/examples/custom_backend.c:638
ma_context_enumerate_devices__sdl
static ma_result ma_context_enumerate_devices__sdl(ma_context *pContext, ma_enum_devices_callback_proc callback, void *pUserData)
Definition: pvrecorder/src/miniaudio/examples/custom_backend.c:176
ma_device_type_capture
@ ma_device_type_capture
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3013
ma_device_descriptor::sampleRate
ma_uint32 sampleRate
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2050
ma_device_info::flags
ma_uint32 flags
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1933
ma_device::channels
ma_uint32 channels
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3626
ma_device_config::deviceType
ma_device_type deviceType
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3102
ma_bool32
ma_uint32 ma_bool32
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1529
ma_waveform_config
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5361
MA_PFN_SDL_QuitSubSystem
void(* MA_PFN_SDL_QuitSubSystem)(ma_uint32 flags)
Definition: pvrecorder/src/miniaudio/examples/custom_backend.c:143
ma_countof
#define ma_countof(x)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:776
ma_format_f32
@ ma_format_f32
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1790
ma_device_id::custom
union ma_device_id::@169 custom
MA_FAILED_TO_OPEN_BACKEND_DEVICE
#define MA_FAILED_TO_OPEN_BACKEND_DEVICE
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1731
ma_format_s32
@ ma_format_s32
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1789
ma_context_post_error
static ma_result ma_context_post_error(ma_context *pContext, ma_device *pDevice, ma_uint32 logLevel, const char *message, ma_result resultCode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:5450
MA_SDL_AudioSpec::callback
MA_SDL_AudioCallback callback
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/examples/custom_backend.c:137
MA_SDL_AudioSpec::size
ma_uint32 size
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/examples/custom_backend.c:136
ma_dlclose
MA_API void ma_dlclose(ma_context *pContext, ma_handle handle)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:5614
ma_context_ex::SDL_QuitSubSystem
ma_proc SDL_QuitSubSystem
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/examples/custom_backend.c:57
ma_device_info::nativeDataFormatCount
ma_uint32 nativeDataFormatCount
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1927
ma_context_ex::hSDL
ma_handle hSDL
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/examples/custom_backend.c:55
MA_DEFAULT_CAPTURE_DEVICE_NAME
#define MA_DEFAULT_CAPTURE_DEVICE_NAME
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:5418
ma_format
ma_format
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1779
ma_device::format
ma_format format
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3625
ma_backend_callbacks::onContextGetDeviceInfo
ma_result(* onContextGetDeviceInfo)(ma_context *pContext, ma_device_type deviceType, const ma_device_id *pDeviceID, ma_device_info *pDeviceInfo)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2127
ma_device_type_playback
@ ma_device_type_playback
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3012
ma_backend_callbacks::onContextInit
ma_result(* onContextInit)(ma_context *pContext, const ma_context_config *pConfig, ma_backend_callbacks *pCallbacks)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2124
ma_device_info::format
ma_format format
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1930
ma_format_to_sdl
MA_SDL_AudioFormat ma_format_to_sdl(ma_format format)
Definition: pvrecorder/src/miniaudio/examples/custom_backend.c:150
ma_device_descriptor::channelMap
ma_channel channelMap[MA_MAX_CHANNELS]
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2051
MA_DEFAULT_PLAYBACK_DEVICE_NAME
#define MA_DEFAULT_PLAYBACK_DEVICE_NAME
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:5417
ma_format_s24
@ ma_format_s24
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1788
MA_SDL_AudioFormat
ma_uint16 MA_SDL_AudioFormat
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/examples/custom_backend.c:125
ma_backend_callbacks::onDeviceUninit
ma_result(* onDeviceUninit)(ma_device *pDevice)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2129
DEVICE_FORMAT
#define DEVICE_FORMAT
Definition: pvrecorder/src/miniaudio/examples/custom_backend.c:636
ma_device_config::dataCallback
ma_device_callback_proc dataCallback
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3110
MA_SDL_AudioFormat
ma_uint16 MA_SDL_AudioFormat
Definition: pvrecorder/src/miniaudio/examples/custom_backend.c:125
MA_SDL_AudioSpec::freq
int freq
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/examples/custom_backend.c:130
MA_AUDIO_S16
#define MA_AUDIO_S16
Definition: pvrecorder/src/miniaudio/examples/custom_backend.c:102
ma_device::internalFormat
ma_format internalFormat
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3628
ma_context_ex
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/examples/custom_backend.c:49
ma_format_unknown
@ ma_format_unknown
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1785
ma_device_start__sdl
static ma_result ma_device_start__sdl(ma_device *pDevice)
Definition: pvrecorder/src/miniaudio/examples/custom_backend.c:477
ma_device_uninit__sdl
static ma_result ma_device_uninit__sdl(ma_device *pDevice)
Definition: pvrecorder/src/miniaudio/examples/custom_backend.c:459
device
ma_device device
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/tests/test_deviceio/ma_test_deviceio.c:57
ma_backend_callbacks
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2122
MA_PFN_SDL_OpenAudioDevice
MA_SDL_AudioDeviceID(* MA_PFN_SDL_OpenAudioDevice)(const char *device, int iscapture, const MA_SDL_AudioSpec *desired, MA_SDL_AudioSpec *obtained, int allowed_changes)
Definition: pvrecorder/src/miniaudio/examples/custom_backend.c:147
ma_enum_devices_callback_proc
ma_bool32(* ma_enum_devices_callback_proc)(ma_context *pContext, ma_device_type deviceType, const ma_device_info *pInfo, void *pUserData)
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3208
ma_next_power_of_2
static MA_INLINE unsigned int ma_next_power_of_2(unsigned int x)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:1773
ma_device_config::capture
struct ma_device_config::@98 capture
ma_device_config::performanceProfile
ma_performance_profile performanceProfile
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3107
ma_context_uninit
ma_result ma_context_uninit(ma_context *pContext)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:26757
ma_result
int ma_result
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1658
ma_context_config_init
ma_context_config ma_context_config_init(void)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:26542
ma_device_info::id
ma_device_id id
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3076
MA_SDL_AudioSpec
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/examples/custom_backend.c:128
ma_audio_callback_capture__sdl
void ma_audio_callback_capture__sdl(void *pUserData, ma_uint8 *pBuffer, int bufferSizeInBytes)
Definition: pvrecorder/src/miniaudio/examples/custom_backend.c:320
ma_device_descriptor::pDeviceID
const ma_device_id * pDeviceID
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2046
ma_context_ex::SDL_InitSubSystem
ma_proc SDL_InitSubSystem
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/examples/custom_backend.c:56
ma_device_descriptor::periodSizeInFrames
ma_uint32 periodSizeInFrames
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2052
ma_context_ex::sdl
struct ma_context_ex::@133 sdl
ma_waveform_init
ma_result ma_waveform_init(const ma_waveform_config *pConfig, ma_waveform *pWaveform)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:45445
ma_dlopen
MA_API ma_handle ma_dlopen(ma_context *pContext, const char *filename)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:5580
ma_audio_callback_playback__sdl
void ma_audio_callback_playback__sdl(void *pUserData, ma_uint8 *pBuffer, int bufferSizeInBytes)
Definition: pvrecorder/src/miniaudio/examples/custom_backend.c:329
MA_SDL_AUDIO_ALLOW_ANY_CHANGE
#define MA_SDL_AUDIO_ALLOW_ANY_CHANGE
Definition: pvrecorder/src/miniaudio/examples/custom_backend.c:108
ma_device_ex::deviceIDPlayback
int deviceIDPlayback
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/examples/custom_backend.c:73
ma_device_descriptor
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2044
ma_context_uninit__sdl
static ma_result ma_context_uninit__sdl(ma_context *pContext)
Definition: pvrecorder/src/miniaudio/examples/custom_backend.c:513
MA_PFN_SDL_InitSubSystem
int(* MA_PFN_SDL_InitSubSystem)(ma_uint32 flags)
Definition: pvrecorder/src/miniaudio/examples/custom_backend.c:142
ma_format_s16
@ ma_format_s16
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1787
ma_device_info
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3073
MA_SDL_AudioSpec::format
MA_SDL_AudioFormat format
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/examples/custom_backend.c:131
ma_device::pUserData
void * pUserData
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3592
ma_device_id
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3055
ma_context_init__sdl
static ma_result ma_context_init__sdl(ma_context *pContext, const ma_context_config *pConfig, ma_backend_callbacks *pCallbacks)
Definition: pvrecorder/src/miniaudio/examples/custom_backend.c:528
ma_backend_callbacks::onContextUninit
ma_result(* onContextUninit)(ma_context *pContext)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2125
ma_get_standard_channel_map
void ma_get_standard_channel_map(ma_standard_channel_map standardChannelMap, ma_uint32 channels, ma_channel channelMap[MA_MAX_CHANNELS])
ma_device_descriptor::periodCount
ma_uint32 periodCount
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2054
ma_context_ex::SDL_OpenAudioDevice
ma_proc SDL_OpenAudioDevice
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/examples/custom_backend.c:61
MA_SDL_AudioCallback
void(* MA_SDL_AudioCallback)(void *userdata, ma_uint8 *stream, int len)
Definition: pvrecorder/src/miniaudio/examples/custom_backend.c:124
ma_device_ex
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/examples/custom_backend.c:67
MA_ASSERT
#define MA_ASSERT(condition)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:770
ma_waveform_config_init
ma_waveform_config ma_waveform_config_init(ma_format format, ma_uint32 channels, ma_uint32 sampleRate, ma_waveform_type type, double amplitude, double frequency)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:45369
ma_backend_custom
@ ma_backend_custom
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1657
MA_PFN_SDL_PauseAudioDevice
void(* MA_PFN_SDL_PauseAudioDevice)(MA_SDL_AudioDeviceID dev, int pause_on)
Definition: pvrecorder/src/miniaudio/examples/custom_backend.c:148
ma_context_init__custom_loader
static ma_result ma_context_init__custom_loader(ma_context *pContext, const ma_context_config *pConfig, ma_backend_callbacks *pCallbacks)
Definition: pvrecorder/src/miniaudio/examples/custom_backend.c:611
ma_device_info::name
char name[256]
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3077
ma_backend_callbacks::onContextEnumerateDevices
ma_result(* onContextEnumerateDevices)(ma_context *pContext, ma_enum_devices_callback_proc callback, void *pUserData)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2126
ma_device_stop__sdl
static ma_result ma_device_stop__sdl(ma_device *pDevice)
Definition: pvrecorder/src/miniaudio/examples/custom_backend.c:495
ma_device_init_internal__sdl
static ma_result ma_device_init_internal__sdl(ma_device_ex *pDeviceEx, const ma_device_config *pConfig, ma_device_descriptor *pDescriptor)
Definition: pvrecorder/src/miniaudio/examples/custom_backend.c:338
MA_NO_BACKEND
#define MA_NO_BACKEND
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1718
ma_waveform_type_sine
@ ma_waveform_type_sine
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5359
MA_AUDIO_F32
#define MA_AUDIO_F32
Definition: pvrecorder/src/miniaudio/examples/custom_backend.c:104
ma_device_info::nativeDataFormats
struct ma_device_info::@170 nativeDataFormats[/*ma_format_count *ma_standard_sample_rate_count *MA_MAX_CHANNELS */64]
ma_uint32
uint32_t ma_uint32
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1503
ma_device_handle_backend_data_callback
MA_API ma_result ma_device_handle_backend_data_callback(ma_device *pDevice, void *pOutput, const void *pInput, ma_uint32 frameCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:27678
ma_device_ex::sdl
struct ma_device_ex::@134 sdl
ma_waveform
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:5373
ma_format_u8
@ ma_format_u8
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1786
ma_device_config::format
ma_format format
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3128
MA_SDL_INIT_AUDIO
#define MA_SDL_INIT_AUDIO
Definition: pvrecorder/src/miniaudio/examples/custom_backend.c:100
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_device::pContext
ma_context * pContext
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3586
ma_device_id::i
int i
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1889
MA_PFN_SDL_GetNumAudioDevices
int(* MA_PFN_SDL_GetNumAudioDevices)(int iscapture)
Definition: pvrecorder/src/miniaudio/examples/custom_backend.c:144
ma_standard_channel_map_default
@ ma_standard_channel_map_default
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1813
MA_PFN_SDL_CloseAudioDevice
void(* MA_PFN_SDL_CloseAudioDevice)(MA_SDL_AudioDeviceID dev)
Definition: pvrecorder/src/miniaudio/examples/custom_backend.c:146
ma_post_error
static ma_result ma_post_error(ma_device *pDevice, ma_uint32 logLevel, const char *message, ma_result resultCode)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:5456
ma_copy_pcm_frames
MA_API void ma_copy_pcm_frames(void *dst, const void *src, ma_uint64 frameCount, ma_format format, ma_uint32 channels)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:27780
MA_LOG_LEVEL_ERROR
#define MA_LOG_LEVEL_ERROR
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1591
ma_backend_callbacks::onDeviceStart
ma_result(* onDeviceStart)(ma_device *pDevice)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2130
ma_device_config::channels
ma_uint32 channels
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3129
MA_AUDIO_U8
#define MA_AUDIO_U8
Definition: pvrecorder/src/miniaudio/examples/custom_backend.c:101
ma_waveform_read_pcm_frames
ma_uint64 ma_waveform_read_pcm_frames(ma_waveform *pWaveform, void *pFramesOut, ma_uint64 frameCount)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:45751
MA_ERROR
#define MA_ERROR
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1660
MA_AUDIO_S32
#define MA_AUDIO_S32
Definition: pvrecorder/src/miniaudio/examples/custom_backend.c:103
MA_SDL_AudioSpec::padding
ma_uint16 padding
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/examples/custom_backend.c:135
MA_SDL_AudioSpec::silence
ma_uint8 silence
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/examples/custom_backend.c:133
ma_backend_callbacks::onDeviceStop
ma_result(* onDeviceStop)(ma_device *pDevice)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2131
python.test_porcupine.argv
argv
Definition: test_porcupine.py:158
ma_context
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3210
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_device_info::channels
ma_uint32 channels
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1931
ma_device::capture
struct ma_device::@116 capture
data_callback
void data_callback(ma_device *pDevice, void *pOutput, const void *pInput, ma_uint32 frameCount)
Definition: pvrecorder/src/miniaudio/examples/custom_backend.c:640
ma_device_type
ma_device_type
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3010
ma_handle
void * ma_handle
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1533
MA_TRUE
#define MA_TRUE
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1530
ma_context_init
ma_result ma_context_init(const ma_backend backends[], ma_uint32 backendCount, const ma_context_config *pConfig, ma_context *pContext)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:26550
ma_device_init__sdl
static ma_result ma_device_init__sdl(ma_device *pDevice, const ma_device_config *pConfig, ma_device_descriptor *pDescriptorPlayback, ma_device_descriptor *pDescriptorCapture)
Definition: pvrecorder/src/miniaudio/examples/custom_backend.c:425
MA_SUCCESS
#define MA_SUCCESS
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1659
main
int main(int argc, char **argv)
Definition: pvrecorder/src/miniaudio/examples/custom_backend.c:658
MA_SDL_AudioDeviceID
ma_uint32 MA_SDL_AudioDeviceID
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/examples/custom_backend.c:126
ma_context_ex::SDL_GetNumAudioDevices
ma_proc SDL_GetNumAudioDevices
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/examples/custom_backend.c:58
ma_context_ex::SDL_CloseAudioDevice
ma_proc SDL_CloseAudioDevice
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/examples/custom_backend.c:60
ma_backend_callbacks::onDeviceInit
ma_result(* onDeviceInit)(ma_device *pDevice, const ma_device_config *pConfig, ma_device_descriptor *pDescriptorPlayback, ma_device_descriptor *pDescriptorCapture)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2128
MA_ZERO_OBJECT
#define MA_ZERO_OBJECT(p)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:774
MA_SDL_AudioSpec::channels
ma_uint8 channels
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/examples/custom_backend.c:132
ma_context_ex::SDL_PauseAudioDevice
ma_proc SDL_PauseAudioDevice
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/examples/custom_backend.c:62
ma_context_config::custom
ma_backend_callbacks custom
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2168
ma_context_ex::SDL_GetAudioDeviceName
ma_proc SDL_GetAudioDeviceName
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/examples/custom_backend.c:59
ma_device_descriptor::format
ma_format format
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2048
ma_backend
ma_backend
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:2793
MA_SDL_AudioDeviceID
ma_uint32 MA_SDL_AudioDeviceID
Definition: pvrecorder/src/miniaudio/examples/custom_backend.c:126
ma_device_ex::device
ma_device device
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/examples/custom_backend.c:69
DEVICE_CHANNELS
#define DEVICE_CHANNELS
Definition: pvrecorder/src/miniaudio/examples/custom_backend.c:637
ma_device_info::sampleRate
ma_uint32 sampleRate
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:1932
ma_device_info::isDefault
ma_bool32 isDefault
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3096
ma_device_descriptor::channels
ma_uint32 channels
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.h:2049
MA_DEFAULT_SAMPLE_RATE
#define MA_DEFAULT_SAMPLE_RATE
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:606
ma_uint16
uint16_t ma_uint16
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:1501
ma_device_config::playback
struct ma_device_config::@97 playback
ma_device_type_duplex
@ ma_device_type_duplex
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3014
ma_calculate_buffer_size_in_frames_from_descriptor
MA_API ma_uint32 ma_calculate_buffer_size_in_frames_from_descriptor(const ma_device_descriptor *pDescriptor, ma_uint32 nativeSampleRate, ma_performance_profile performanceProfile)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:27717
ma_device::playback
struct ma_device::@115 playback
ma_device::type
ma_device_type type
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3587
MA_ZERO_MEMORY
#define MA_ZERO_MEMORY(p, sz)
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/extras/miniaudio_split/miniaudio.c:746
MA_SDL_AudioSpec::userdata
void * userdata
Definition: porcupine/demo/c/pvrecorder/src/miniaudio/examples/custom_backend.c:138
ma_device_config::pUserData
void * pUserData
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3112
ma_context_config
Definition: porcupine/demo/c/dr_libs/tests/external/miniaudio/miniaudio.h:3160


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