mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-26 10:14:04 +02:00
Add PS Vita backend.
This commit is contained in:
+408
@@ -3740,6 +3740,7 @@ example, ALSA, which is specific to Linux, will not be included in the Windows b
|
||||
| Web Audio | ma_device_backend_webaudio | Web (via Emscripten) |
|
||||
| Dreamcast | ma_device_backend_dreamcast | KallistiOS |
|
||||
| XAudio | ma_device_backend_xaudio | NXDK |
|
||||
| PS Vita | ma_device_backend_vita | Vita SDK |
|
||||
| Null | ma_device_backend_null | Cross Platform (not used on Web) |
|
||||
+-------------+------------------------------+--------------------------------------------------------+
|
||||
|
||||
@@ -3883,6 +3884,29 @@ use a period size smaller than 1024, but in my testing I found that it can resul
|
||||
are not forced to use this configuration, but if you deviate from it miniaudio will need to do data
|
||||
conversion.
|
||||
|
||||
15.8. PlayStation Vita
|
||||
----------------------
|
||||
The Vita backend uses Vita SDK.
|
||||
|
||||
The following device configuration is optimal:
|
||||
|
||||
Format: ma_foramt_s16
|
||||
Channels: 2
|
||||
Sample Rate: 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100 or 48000
|
||||
Period Size: Multiple of 64, between 64 and 65472
|
||||
noFixedSizedCallback: True
|
||||
|
||||
If you follow this configuration you can be guaranteed an optimized passthrough pipeline, except
|
||||
when using a sample rate other than 48000 on the Main port (see below).
|
||||
|
||||
The BGM port (SCE_AUDIO_OUT_PORT_TYPE_BGM) is used by default. You can use the Main port by
|
||||
configuring it in the device config:
|
||||
|
||||
deviceConfig.vita.portType = MA_VITA_PORT_TYPE_MAIN; // Or MA_VITA_PORT_TYPE_BGM
|
||||
|
||||
When using MA_VITA_PORT_TYPE_MAIN, the native sample rate will always be 48000 and using anything
|
||||
else will invoke miniaudio's resampler which will have overhead.
|
||||
|
||||
|
||||
16. Optimization Tips
|
||||
=====================
|
||||
@@ -7482,6 +7506,34 @@ MA_API ma_device_config_xaudio ma_device_config_xaudio_init(void);
|
||||
/* END miniaudio_xaudio.h */
|
||||
|
||||
|
||||
/* BEG miniaudio_vita.h */
|
||||
extern ma_device_backend_vtable* ma_device_backend_vita;
|
||||
MA_API ma_device_backend_vtable* ma_vita_get_vtable(void);
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int _unused;
|
||||
} ma_context_config_vita;
|
||||
|
||||
MA_API ma_context_config_vita ma_context_config_vita_init(void);
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
MA_VITA_PORT_TYPE_BGM = 0,
|
||||
MA_VITA_PORT_TYPE_MAIN = 1
|
||||
} ma_vita_port_type;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ma_vita_port_type portType;
|
||||
} ma_device_config_vita;
|
||||
|
||||
MA_API ma_device_config_vita ma_device_config_vita_init(void);
|
||||
/* END miniaudio_vita.h */
|
||||
|
||||
|
||||
/* BEG miniaudio_null.h */
|
||||
typedef struct ma_context_config_null
|
||||
{
|
||||
@@ -7914,6 +7966,7 @@ struct ma_device_config
|
||||
ma_device_config_webaudio webaudio;
|
||||
ma_device_config_dreamcast dreamcast;
|
||||
ma_device_config_xaudio xaudio;
|
||||
ma_device_config_vita vita;
|
||||
ma_device_config_null null_backend;
|
||||
};
|
||||
|
||||
@@ -8055,6 +8108,7 @@ struct ma_context_config
|
||||
ma_context_config_webaudio webaudio;
|
||||
ma_context_config_dreamcast dreamcast;
|
||||
ma_context_config_xaudio xaudio;
|
||||
ma_context_config_vita vita;
|
||||
ma_context_config_null null_backend;
|
||||
};
|
||||
|
||||
@@ -20338,6 +20392,9 @@ BACKENDS
|
||||
#if defined(MA_XBOX)
|
||||
#define MA_SUPPORT_XAUDIO
|
||||
#endif
|
||||
#if defined(MA_VITA)
|
||||
#define MA_SUPPORT_VITA
|
||||
#endif
|
||||
|
||||
/* All platforms should support custom backends. */
|
||||
#define MA_SUPPORT_CUSTOM
|
||||
@@ -20396,6 +20453,9 @@ BACKENDS
|
||||
#if defined(MA_SUPPORT_XAUDIO) && !defined(MA_NO_XAUDIO) && (!defined(MA_ENABLE_ONLY_SPECIFIC_BACKENDS) || defined(MA_ENABLE_XAUDIO))
|
||||
#define MA_HAS_XAUDIO
|
||||
#endif
|
||||
#if defined(MA_SUPPORT_VITA) && !defined(MA_NO_VITA) && (!defined(MA_ENABLE_ONLY_SPECIFIC_BACKENDS) || defined(MA_ENABLE_VITA))
|
||||
#define MA_HAS_VITA
|
||||
#endif
|
||||
#if defined(MA_SUPPORT_NULL) && !defined(MA_NO_NULL) && (!defined(MA_ENABLE_ONLY_SPECIFIC_BACKENDS) || defined(MA_ENABLE_NULL))
|
||||
#define MA_HAS_NULL
|
||||
#endif
|
||||
@@ -48766,6 +48826,347 @@ MA_API ma_device_config_xaudio ma_device_config_xaudio_init(void)
|
||||
/* END miniaudio_xaudio.c */
|
||||
|
||||
|
||||
/* BEG miniaudio_vita.c */
|
||||
#if defined(MA_HAS_VITA)
|
||||
#include <psp2/audioout.h>
|
||||
|
||||
typedef struct ma_context_state_vita
|
||||
{
|
||||
int _unused;
|
||||
} ma_context_state_vita;
|
||||
|
||||
typedef struct ma_device_state_vita
|
||||
{
|
||||
int port;
|
||||
ma_bool32 isRunning; /* Used for tracking whether or not the background thread should be terminated. */
|
||||
ma_thread thread; /* Need to call sceAudioOutOutput() from a separate thread because it is always blocking. */
|
||||
ma_uint32 subBufferIndex;
|
||||
ma_uint32 validSubBufferCount;
|
||||
void* pSubBuffers;
|
||||
} ma_device_state_vita;
|
||||
|
||||
|
||||
static ma_context_state_vita* ma_context_get_backend_state__vita(ma_context* pContext)
|
||||
{
|
||||
return (ma_context_state_vita*)ma_context_get_backend_state(pContext);
|
||||
}
|
||||
|
||||
static ma_device_state_vita* ma_device_get_backend_state__vita(ma_device* pDevice)
|
||||
{
|
||||
return (ma_device_state_vita*)ma_device_get_backend_state(pDevice);
|
||||
}
|
||||
|
||||
|
||||
static void ma_backend_info__vita(ma_device_backend_info* pBackendInfo)
|
||||
{
|
||||
pBackendInfo->pName = "PlayStation Vita";
|
||||
}
|
||||
|
||||
static ma_result ma_context_init__vita(ma_context* pContext, const void* pContextBackendConfig, void** ppContextState)
|
||||
{
|
||||
ma_context_state_vita* pContextStateVita;
|
||||
const ma_context_config_vita* pContextConfigVita = (ma_context_config_vita*)pContextBackendConfig;
|
||||
|
||||
pContextStateVita = (ma_context_state_vita*)ma_calloc(sizeof(*pContextStateVita), ma_context_get_allocation_callbacks(pContext));
|
||||
if (pContextStateVita == NULL) {
|
||||
return MA_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
(void)pContextConfigVita;
|
||||
(void)pContext;
|
||||
|
||||
*ppContextState = pContextStateVita;
|
||||
|
||||
return MA_SUCCESS;
|
||||
}
|
||||
|
||||
static void ma_context_uninit__vita(ma_context* pContext)
|
||||
{
|
||||
ma_context_state_vita* pContextStateVita = ma_context_get_backend_state__vita(pContext);
|
||||
ma_free(pContextStateVita, ma_context_get_allocation_callbacks(pContext));
|
||||
}
|
||||
|
||||
static ma_result ma_context_enumerate_devices__vita(ma_context* pContext, ma_enum_devices_callback_proc callback, void* pCallbackUserData)
|
||||
{
|
||||
ma_context_state_vita* pContextStateVita = ma_context_get_backend_state__vita(pContext);
|
||||
ma_device_info deviceInfo;
|
||||
ma_device_enumeration_result enumerationResult;
|
||||
|
||||
(void)pContextStateVita;
|
||||
|
||||
/* Playback. */
|
||||
MA_ZERO_OBJECT(&deviceInfo);
|
||||
deviceInfo.isDefault = MA_TRUE;
|
||||
deviceInfo.id.custom.i = 0;
|
||||
ma_strncpy_s(deviceInfo.name, sizeof(deviceInfo.name), "Default Playback Device", (size_t)-1);
|
||||
|
||||
/* Only s16 and mono/stereo is natively supported. */
|
||||
ma_device_info_add_native_data_format(&deviceInfo, ma_format_s16, 1, 2, 8000, 48000);
|
||||
|
||||
enumerationResult = callback(ma_device_type_playback, &deviceInfo, pCallbackUserData);
|
||||
if (enumerationResult == MA_DEVICE_ENUMERATION_ABORT) {
|
||||
return MA_SUCCESS;
|
||||
}
|
||||
|
||||
return MA_SUCCESS;
|
||||
}
|
||||
|
||||
static void* ma_device_get_sub_buffer__vita(ma_device* pDevice, ma_uint32 subBufferIndex)
|
||||
{
|
||||
ma_device_state_vita* pDeviceStateVita = ma_device_get_backend_state__vita(pDevice);
|
||||
return ma_offset_ptr(pDeviceStateVita->pSubBuffers, pDevice->playback.internalPeriodSizeInFrames * ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels) * subBufferIndex);
|
||||
}
|
||||
|
||||
static ma_thread_result MA_THREADCALL ma_device_audio_thread__vita(void* pUserData)
|
||||
{
|
||||
ma_device* pDevice = (ma_device*)pUserData;
|
||||
ma_device_state_vita* pDeviceStateVita = ma_device_get_backend_state__vita(pDevice);
|
||||
|
||||
while (ma_atomic_load_explicit_32(&pDeviceStateVita->isRunning, ma_atomic_memory_order_relaxed)) {
|
||||
if (ma_atomic_load_explicit_32(&pDeviceStateVita->validSubBufferCount, ma_atomic_memory_order_acquire) > 0) {
|
||||
ma_uint32 subBufferIndex = ma_atomic_load_explicit_32(&pDeviceStateVita->subBufferIndex, ma_atomic_memory_order_relaxed);
|
||||
|
||||
sceAudioOutOutput(pDeviceStateVita->port, ma_device_get_sub_buffer__vita(pDevice, subBufferIndex));
|
||||
|
||||
ma_atomic_store_explicit_32(&pDeviceStateVita->subBufferIndex, (subBufferIndex + 1) & 1, ma_atomic_memory_order_relaxed);
|
||||
ma_atomic_fetch_sub_explicit_32(&pDeviceStateVita->validSubBufferCount, 1, ma_atomic_memory_order_release);
|
||||
} else {
|
||||
/* Just a dumb sleep so we don't peg the CPU while the device is not stopped. */
|
||||
ma_sleep(10);
|
||||
}
|
||||
}
|
||||
|
||||
return (ma_thread_result)0;
|
||||
}
|
||||
|
||||
static ma_result ma_device_init__vita(ma_device* pDevice, const void* pDeviceBackendConfig, ma_device_descriptor* pDescriptorPlayback, ma_device_descriptor* pDescriptorCapture, void** ppDeviceState)
|
||||
{
|
||||
ma_result result;
|
||||
ma_device_state_vita* pDeviceStateVita;
|
||||
ma_device_config_vita* pDeviceConfigVita = (ma_device_config_vita*)pDeviceBackendConfig;
|
||||
ma_context_state_vita* pContextStateVita = ma_context_get_backend_state__vita(ma_device_get_context(pDevice));
|
||||
ma_device_config_vita defaultConfig;
|
||||
ma_device_type deviceType = ma_device_get_type(pDevice);
|
||||
ma_log* pLog = ma_device_get_log(pDevice);
|
||||
ma_format format;
|
||||
ma_uint32 channels;
|
||||
ma_uint32 sampleRate;
|
||||
ma_uint32 periodSizeInFrames;
|
||||
SceAudioOutPortType portType;
|
||||
|
||||
(void)pContextStateVita;
|
||||
(void)pDescriptorCapture;
|
||||
|
||||
/* Use a default config if one was not provided. This is not mandated by miniaudio, but it's good practice. */
|
||||
if (pDeviceConfigVita == NULL) {
|
||||
defaultConfig = ma_device_config_vita_init();
|
||||
pDeviceConfigVita = &defaultConfig;
|
||||
}
|
||||
|
||||
/* Return an error for any unsupported device types. */
|
||||
if (deviceType != ma_device_type_playback) {
|
||||
return MA_DEVICE_TYPE_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
pDeviceStateVita = (ma_device_state_vita*)ma_calloc(sizeof(*pDeviceStateVita), ma_device_get_allocation_callbacks(pDevice));
|
||||
if (pDeviceStateVita == NULL) {
|
||||
return MA_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
/* Port type. */
|
||||
portType = SCE_AUDIO_OUT_PORT_TYPE_BGM;
|
||||
if (pDeviceConfigVita->portType == MA_VITA_PORT_TYPE_MAIN) {
|
||||
portType = SCE_AUDIO_OUT_PORT_TYPE_MAIN;
|
||||
}
|
||||
|
||||
/* Format is always s16. */
|
||||
format = ma_format_s16;
|
||||
|
||||
/* Channels is always mono or stereo. Default to stereo. */
|
||||
channels = pDescriptorPlayback->channels;
|
||||
if (channels != 1 && channels != 2) {
|
||||
channels = 1;
|
||||
}
|
||||
|
||||
/* Sample rate. */
|
||||
sampleRate = 0;
|
||||
|
||||
if (pDescriptorPlayback->sampleRate != 0) {
|
||||
if (portType == SCE_AUDIO_OUT_PORT_TYPE_BGM) {
|
||||
ma_uint32 bgmSampleRates[] = {8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000};
|
||||
ma_uint32 iSampleRate;
|
||||
|
||||
for (iSampleRate = 0; iSampleRate < ma_countof(bgmSampleRates); iSampleRate += 1) {
|
||||
if (pDescriptorPlayback->sampleRate == bgmSampleRates[iSampleRate]) {
|
||||
sampleRate = bgmSampleRates[iSampleRate];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (sampleRate == 0) {
|
||||
sampleRate = 48000;
|
||||
}
|
||||
|
||||
|
||||
/* The period size must be a multiple of 64. */
|
||||
periodSizeInFrames = ma_calculate_buffer_size_in_frames_from_descriptor(pDescriptorPlayback, sampleRate);
|
||||
periodSizeInFrames = ma_clamp((periodSizeInFrames + 63) & ~63, SCE_AUDIO_MIN_LEN, SCE_AUDIO_MAX_LEN);
|
||||
|
||||
pDeviceStateVita->pSubBuffers = ma_malloc(periodSizeInFrames * ma_get_bytes_per_frame(format, channels) * 2, ma_device_get_allocation_callbacks(pDevice));
|
||||
if (pDeviceStateVita->pSubBuffers == NULL) {
|
||||
return MA_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
pDeviceStateVita->port = sceAudioOutOpenPort(portType, (int)periodSizeInFrames, (int)sampleRate, (channels == 1) ? SCE_AUDIO_OUT_MODE_MONO : SCE_AUDIO_OUT_MODE_STEREO);
|
||||
if (pDeviceStateVita->port < 0) {
|
||||
ma_free(pDeviceStateVita->pSubBuffers, ma_device_get_allocation_callbacks(pDevice));
|
||||
ma_log_postf(pLog, MA_LOG_LEVEL_ERROR, "[Vita] Failed to open port.");
|
||||
return MA_ERROR;
|
||||
}
|
||||
|
||||
/* Make sure the running status is set appropriately so the audio thread doesn't immediately terminate itself. */
|
||||
ma_atomic_store_explicit_32(&pDeviceStateVita->isRunning, 1, ma_atomic_memory_order_relaxed);
|
||||
|
||||
/*
|
||||
Because sceAudioOutOutput() is always blocking, in order to do non-blocking processing, we'll need to call
|
||||
it on a separate thread. Make sure the thread is created last.
|
||||
*/
|
||||
result = ma_thread_create(&pDeviceStateVita->thread, ma_thread_priority_default, 0, ma_device_audio_thread__vita, pDevice, ma_device_get_allocation_callbacks(pDevice));
|
||||
if (result != MA_SUCCESS) {
|
||||
sceAudioOutReleasePort(pDeviceStateVita->port);
|
||||
ma_free(pDeviceStateVita->pSubBuffers, ma_device_get_allocation_callbacks(pDevice));
|
||||
ma_log_postf(pLog, MA_LOG_LEVEL_ERROR, "[Vita] Failed to create audio thread.");
|
||||
return MA_ERROR;
|
||||
}
|
||||
|
||||
/* Update the descriptor with the actual internal settings. */
|
||||
pDescriptorPlayback->format = format;
|
||||
pDescriptorPlayback->channels = channels;
|
||||
pDescriptorPlayback->sampleRate = sampleRate;
|
||||
pDescriptorPlayback->periodSizeInFrames = periodSizeInFrames;
|
||||
pDescriptorPlayback->periodCount = 2;
|
||||
|
||||
*ppDeviceState = pDeviceStateVita;
|
||||
|
||||
return MA_SUCCESS;
|
||||
}
|
||||
|
||||
static void ma_device_uninit__vita(ma_device* pDevice)
|
||||
{
|
||||
ma_device_state_vita* pDeviceStateVita = ma_device_get_backend_state__vita(pDevice);
|
||||
|
||||
/* Kill the thread first. */
|
||||
ma_atomic_store_explicit_32(&pDeviceStateVita->isRunning, 0, ma_atomic_memory_order_relaxed);
|
||||
ma_thread_wait(&pDeviceStateVita->thread);
|
||||
|
||||
sceAudioOutReleasePort(pDeviceStateVita->port);
|
||||
ma_free(pDeviceStateVita->pSubBuffers, ma_device_get_allocation_callbacks(pDevice));
|
||||
ma_free(pDeviceStateVita, ma_device_get_allocation_callbacks(pDevice));
|
||||
}
|
||||
|
||||
static ma_result ma_device_start__vita(ma_device* pDevice)
|
||||
{
|
||||
ma_device_state_vita* pDeviceStateVita = ma_device_get_backend_state__vita(pDevice);
|
||||
|
||||
ma_atomic_store_explicit_32(&pDeviceStateVita->subBufferIndex, 0, ma_atomic_memory_order_relaxed);
|
||||
ma_atomic_store_explicit_32(&pDeviceStateVita->validSubBufferCount, 0, ma_atomic_memory_order_relaxed);
|
||||
|
||||
/* Don't actually do anything here. We start by simply outputting data. Stopping is just not outputting data. */
|
||||
|
||||
return MA_SUCCESS;
|
||||
}
|
||||
|
||||
static ma_result ma_device_stop__vita(ma_device* pDevice)
|
||||
{
|
||||
ma_device_state_vita* pDeviceStateVita = ma_device_get_backend_state__vita(pDevice);
|
||||
|
||||
/* Wait for the buffers to be drained. */
|
||||
while (ma_atomic_load_explicit_32(&pDeviceStateVita->validSubBufferCount, ma_atomic_memory_order_relaxed) > 0) {
|
||||
ma_sleep(1);
|
||||
}
|
||||
|
||||
return MA_SUCCESS;
|
||||
}
|
||||
|
||||
static ma_result ma_device_step__vita(ma_device* pDevice, ma_blocking_mode blockingMode)
|
||||
{
|
||||
ma_device_state_vita* pDeviceStateVita = ma_device_get_backend_state__vita(pDevice);
|
||||
|
||||
for (;;) {
|
||||
if (!ma_device_is_started(pDevice)) {
|
||||
return MA_DEVICE_NOT_STARTED;
|
||||
}
|
||||
|
||||
if (ma_atomic_load_explicit_32(&pDeviceStateVita->validSubBufferCount, ma_atomic_memory_order_acquire) < 2) {
|
||||
ma_uint32 subBufferIndex = ma_atomic_load_explicit_32(&pDeviceStateVita->subBufferIndex, ma_atomic_memory_order_relaxed);
|
||||
ma_device_handle_backend_data_callback(pDevice, ma_device_get_sub_buffer__vita(pDevice, subBufferIndex), NULL, pDevice->playback.internalPeriodSizeInFrames);
|
||||
ma_atomic_fetch_add_explicit_32(&pDeviceStateVita->validSubBufferCount, 1, ma_atomic_memory_order_release);
|
||||
|
||||
return MA_SUCCESS;
|
||||
}
|
||||
|
||||
/* Getting here means there was no data to process. */
|
||||
if (blockingMode == MA_BLOCKING_MODE_NON_BLOCKING) {
|
||||
return MA_SUCCESS;
|
||||
}
|
||||
|
||||
/* Getting here means there was no data to process and we're running in blocking mode. Sleep for a bit and keep trying. */
|
||||
ma_sleep(1);
|
||||
}
|
||||
}
|
||||
|
||||
static void ma_device_wakeup__vita(ma_device* pDevice)
|
||||
{
|
||||
/* Nothing to do here. */
|
||||
(void)pDevice;
|
||||
}
|
||||
|
||||
static ma_device_backend_vtable ma_gDeviceBackendVTable_Vita =
|
||||
{
|
||||
ma_backend_info__vita,
|
||||
ma_context_init__vita,
|
||||
ma_context_uninit__vita,
|
||||
ma_context_enumerate_devices__vita,
|
||||
ma_device_init__vita,
|
||||
ma_device_uninit__vita,
|
||||
ma_device_start__vita,
|
||||
ma_device_stop__vita,
|
||||
ma_device_step__vita,
|
||||
ma_device_wakeup__vita
|
||||
};
|
||||
|
||||
ma_device_backend_vtable* ma_device_backend_vita = &ma_gDeviceBackendVTable_Vita;
|
||||
#else
|
||||
ma_device_backend_vtable* ma_device_backend_vita = NULL;
|
||||
#endif /* MA_HAS_VITA */
|
||||
|
||||
MA_API ma_device_backend_vtable* ma_vita_get_vtable(void)
|
||||
{
|
||||
return ma_device_backend_vita;
|
||||
}
|
||||
|
||||
MA_API ma_context_config_vita ma_context_config_vita_init(void)
|
||||
{
|
||||
ma_context_config_vita config;
|
||||
|
||||
MA_ZERO_OBJECT(&config);
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
MA_API ma_device_config_vita ma_device_config_vita_init(void)
|
||||
{
|
||||
ma_device_config_vita config;
|
||||
|
||||
MA_ZERO_OBJECT(&config);
|
||||
config.portType = MA_VITA_PORT_TYPE_BGM;
|
||||
|
||||
return config;
|
||||
}
|
||||
/* END miniaudio_vita.c */
|
||||
|
||||
|
||||
|
||||
MA_API void ma_get_device_backend_info(ma_device_backend_vtable* pBackendVTable, ma_device_backend_info* pBackendInfo)
|
||||
{
|
||||
@@ -49800,6 +50201,9 @@ static const void* ma_context_config_find_backend_config(const ma_context_config
|
||||
if (pVTable == ma_device_backend_xaudio) {
|
||||
return &pConfig->xaudio;
|
||||
}
|
||||
if (pVTable == ma_device_backend_vita) {
|
||||
return &pConfig->vita;
|
||||
}
|
||||
if (pVTable == ma_device_backend_null) {
|
||||
return &pConfig->null_backend;
|
||||
}
|
||||
@@ -49831,6 +50235,7 @@ MA_API ma_uint32 ma_get_stock_device_backends(ma_device_backend_config* pBackend
|
||||
if (backendsCap > count) { pBackends[count++] = ma_device_backend_config_init(ma_device_backend_webaudio, NULL); }
|
||||
if (backendsCap > count) { pBackends[count++] = ma_device_backend_config_init(ma_device_backend_dreamcast, NULL); }
|
||||
if (backendsCap > count) { pBackends[count++] = ma_device_backend_config_init(ma_device_backend_xaudio, NULL); }
|
||||
if (backendsCap > count) { pBackends[count++] = ma_device_backend_config_init(ma_device_backend_vita, NULL); }
|
||||
if (backendsCap > count) { pBackends[count++] = ma_device_backend_config_init(ma_device_backend_null, NULL); }
|
||||
|
||||
return count;
|
||||
@@ -50302,6 +50707,9 @@ static const void* ma_device_config_find_backend_config(const ma_device_config*
|
||||
if (pVTable == ma_device_backend_xaudio) {
|
||||
return &pConfig->xaudio;
|
||||
}
|
||||
if (pVTable == ma_device_backend_vita) {
|
||||
return &pConfig->vita;
|
||||
}
|
||||
if (pVTable == ma_device_backend_null) {
|
||||
return &pConfig->null_backend;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user