Merge pull request #2 from lucaskyer/miniaudio_audren_slim
Replace SDL by native libnx audio driver
This commit is contained in:
commit
a6132edc1b
|
|
@ -396,7 +396,6 @@ ifeq ($(PLATFORM),PLATFORM_WEB)
|
|||
endif
|
||||
ifeq ($(PLATFORM),PLATFORM_NX)
|
||||
LDLIBS = -lraylib -lEGL -lGLESv2 -lglapi -ldrm_nouveau -lnx -lm
|
||||
LDLIBS += `$(PREFIX)pkg-config --libs sdl2`
|
||||
endif
|
||||
|
||||
# Define source code object files required
|
||||
|
|
|
|||
|
|
@ -64,8 +64,6 @@ ASFLAGS := -g $(ARCH)
|
|||
LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
|
||||
|
||||
LIBS := -lraylib -lEGL -lGLESv2 -lglapi -ldrm_nouveau -lnx -lm
|
||||
# remove the next line if you dont need audio
|
||||
LIBS += `$(PREFIX)pkg-config --libs sdl2`
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# list of directories containing libraries, this must be the top level containing
|
||||
|
|
|
|||
233
src/external/miniaudio_sdl.h
vendored
233
src/external/miniaudio_sdl.h
vendored
|
|
@ -1,233 +0,0 @@
|
|||
/******************************************************************************
|
||||
|
||||
SDL Backend
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
struct
|
||||
{
|
||||
ma_uint32 deviceID;
|
||||
} device_sdl;
|
||||
|
||||
struct
|
||||
{
|
||||
ma_handle hSDL;
|
||||
ma_proc SDL_InitSubSystem;
|
||||
ma_proc SDL_QuitSubSystem;
|
||||
ma_proc SDL_GetNumAudioDevices;
|
||||
ma_proc SDL_GetAudioDeviceName;
|
||||
ma_proc SDL_CloseAudioDevice;
|
||||
ma_proc SDL_OpenAudioDevice;
|
||||
ma_proc SDL_PauseAudioDevice;
|
||||
} context_sdl;
|
||||
|
||||
|
||||
#define MA_SDL_INIT_AUDIO 0x00000010
|
||||
#define MA_AUDIO_U8 0x0008
|
||||
#define MA_AUDIO_S16 0x8010
|
||||
#define MA_AUDIO_S32 0x8020
|
||||
#define MA_AUDIO_F32 0x8120
|
||||
#define MA_SDL_AUDIO_ALLOW_FREQUENCY_CHANGE 0x00000001
|
||||
#define MA_SDL_AUDIO_ALLOW_FORMAT_CHANGE 0x00000002
|
||||
#define MA_SDL_AUDIO_ALLOW_CHANNELS_CHANGE 0x00000004
|
||||
#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)
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL2/SDL_audio.h>
|
||||
|
||||
typedef int (* MA_PFN_SDL_InitSubSystem)(ma_uint32 flags);
|
||||
typedef void (* MA_PFN_SDL_QuitSubSystem)(ma_uint32 flags);
|
||||
typedef int (* MA_PFN_SDL_GetNumAudioDevices)(int iscapture);
|
||||
typedef const char* (* MA_PFN_SDL_GetAudioDeviceName)(int index, int iscapture);
|
||||
typedef void (* MA_PFN_SDL_CloseAudioDevice)(SDL_AudioDeviceID dev);
|
||||
typedef SDL_AudioDeviceID (* MA_PFN_SDL_OpenAudioDevice)(const char* device, int iscapture, const SDL_AudioSpec* desired, SDL_AudioSpec* obtained, int allowed_changes);
|
||||
typedef void (* MA_PFN_SDL_PauseAudioDevice)(SDL_AudioDeviceID dev, int pause_on);
|
||||
|
||||
static SDL_AudioFormat ma_format_to_sdl(ma_format format)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case ma_format_unknown: return 0;
|
||||
case ma_format_u8: return MA_AUDIO_U8;
|
||||
case ma_format_s16: return MA_AUDIO_S16;
|
||||
case ma_format_s24: return MA_AUDIO_S32; // Closest match.
|
||||
case ma_format_s32: return MA_AUDIO_S32;
|
||||
case ma_format_f32: return MA_AUDIO_F32;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static ma_format ma_format_from_sdl(SDL_AudioFormat format)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case MA_AUDIO_U8: return ma_format_u8;
|
||||
case MA_AUDIO_S16: return ma_format_s16;
|
||||
case MA_AUDIO_S32: return ma_format_s32;
|
||||
case MA_AUDIO_F32: return ma_format_f32;
|
||||
default: return ma_format_unknown;
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
MA_ASSERT(pContext != NULL);
|
||||
MA_ASSERT(deviceType == ma_device_type_playback);
|
||||
|
||||
pDeviceInfo->isDefault = MA_TRUE;
|
||||
|
||||
SDL_AudioSpec desiredSpec, obtainedSpec;
|
||||
MA_ZERO_OBJECT(&desiredSpec);
|
||||
|
||||
SDL_AudioDeviceID tempDeviceID = ((MA_PFN_SDL_OpenAudioDevice)context_sdl.SDL_OpenAudioDevice)(NULL, 0, &desiredSpec, &obtainedSpec, MA_SDL_AUDIO_ALLOW_ANY_CHANGE);
|
||||
((MA_PFN_SDL_CloseAudioDevice)context_sdl.SDL_CloseAudioDevice)(tempDeviceID);
|
||||
|
||||
ma_format format = ma_format_from_sdl(obtainedSpec.format);
|
||||
if (format == ma_format_unknown) {
|
||||
format = ma_format_f32;
|
||||
}
|
||||
|
||||
pDeviceInfo->nativeDataFormatCount = 0;
|
||||
ma_device_info_add_native_data_format(pDeviceInfo, format, obtainedSpec.channels, obtainedSpec.freq, 0);
|
||||
|
||||
return MA_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static ma_result ma_device_uninit__sdl(ma_device* pDevice)
|
||||
{
|
||||
MA_ASSERT(pDevice != NULL);
|
||||
|
||||
((MA_PFN_SDL_CloseAudioDevice)context_sdl.SDL_CloseAudioDevice)(device_sdl.deviceID);
|
||||
|
||||
return MA_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static void ma_audio_callback__sdl(void* pUserData, ma_uint8* pBuffer, int bufferSizeInBytes)
|
||||
{
|
||||
ma_device* pDevice = (ma_device*)pUserData;
|
||||
MA_ASSERT(pDevice != NULL);
|
||||
|
||||
ma_uint32 bytesPerFrame = ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
|
||||
ma_uint32 frameCount = (ma_uint32)bufferSizeInBytes / bytesPerFrame;
|
||||
|
||||
ma_device_handle_backend_data_callback(pDevice, pBuffer, NULL, frameCount);
|
||||
}
|
||||
|
||||
static ma_result ma_device_init__sdl(ma_device* pDevice, const ma_device_config* pConfig, ma_device_descriptor* pDescriptorPlayback, ma_device_descriptor* pDescriptorCapture)
|
||||
{
|
||||
MA_ASSERT(pDevice != NULL);
|
||||
MA_ASSERT(pConfig != NULL);
|
||||
MA_ASSERT(pConfig->deviceType == ma_device_type_playback);
|
||||
|
||||
if (pDescriptorPlayback->sampleRate == 0) {
|
||||
pDescriptorPlayback->sampleRate = MA_DEFAULT_SAMPLE_RATE;
|
||||
}
|
||||
|
||||
pDescriptorPlayback->periodSizeInFrames = pDescriptorPlayback->periodCount * ma_calculate_buffer_size_in_frames_from_descriptor(pDescriptorPlayback, pDescriptorPlayback->sampleRate, pConfig->performanceProfile);
|
||||
|
||||
/* SDL wants the buffer size to be a power of 2 for some reason. */
|
||||
if (pDescriptorPlayback->periodSizeInFrames > 32768) {
|
||||
pDescriptorPlayback->periodSizeInFrames = 32768;
|
||||
} else {
|
||||
pDescriptorPlayback->periodSizeInFrames = ma_next_power_of_2(pDescriptorPlayback->periodSizeInFrames);
|
||||
}
|
||||
|
||||
MA_ASSERT(pDescriptorPlayback->periodSizeInFrames <= 32768);
|
||||
|
||||
/* We now have enough information to set up the device. */
|
||||
SDL_AudioSpec desiredSpec, obtainedSpec;
|
||||
MA_ZERO_OBJECT(&desiredSpec);
|
||||
desiredSpec.freq = (int)pDescriptorPlayback->sampleRate;
|
||||
desiredSpec.format = ma_format_to_sdl(pDescriptorPlayback->format);
|
||||
desiredSpec.channels = (ma_uint8)pDescriptorPlayback->channels;
|
||||
desiredSpec.samples = (ma_uint16)pDescriptorPlayback->periodSizeInFrames;
|
||||
desiredSpec.callback = ma_audio_callback__sdl;
|
||||
desiredSpec.userdata = pDevice;
|
||||
|
||||
/* We'll fall back to f32 if we don't have an appropriate mapping between SDL and miniaudio. */
|
||||
if (desiredSpec.format == ma_format_unknown) {
|
||||
desiredSpec.format = MA_AUDIO_F32;
|
||||
}
|
||||
|
||||
device_sdl.deviceID = ((MA_PFN_SDL_OpenAudioDevice)context_sdl.SDL_OpenAudioDevice)(NULL, 0, &desiredSpec, &obtainedSpec, MA_SDL_AUDIO_ALLOW_ANY_CHANGE);
|
||||
|
||||
/* The descriptor needs to be updated with our actual settings. */
|
||||
pDescriptorPlayback->format = ma_format_from_sdl(obtainedSpec.format);
|
||||
pDescriptorPlayback->channels = obtainedSpec.channels;
|
||||
pDescriptorPlayback->sampleRate = (ma_uint32)obtainedSpec.freq;
|
||||
ma_channel_map_init_standard(ma_standard_channel_map_default, pDescriptorPlayback->channelMap, ma_countof(pDescriptorPlayback->channelMap), pDescriptorPlayback->channels);
|
||||
pDescriptorPlayback->periodSizeInFrames = obtainedSpec.samples;
|
||||
pDescriptorPlayback->periodCount = 1; /* SDL doesn't use the notion of period counts, so just set to 1. */
|
||||
|
||||
return MA_SUCCESS;
|
||||
}
|
||||
|
||||
static ma_result ma_device_start__sdl(ma_device* pDevice)
|
||||
{
|
||||
MA_ASSERT(pDevice != NULL);
|
||||
|
||||
((MA_PFN_SDL_PauseAudioDevice)context_sdl.SDL_PauseAudioDevice)(device_sdl.deviceID, 0);
|
||||
|
||||
return MA_SUCCESS;
|
||||
}
|
||||
|
||||
static ma_result ma_device_stop__sdl(ma_device* pDevice)
|
||||
{
|
||||
MA_ASSERT(pDevice != NULL);
|
||||
|
||||
((MA_PFN_SDL_PauseAudioDevice)context_sdl.SDL_PauseAudioDevice)(device_sdl.deviceID, 1);
|
||||
|
||||
ma_device__set_state(pDevice, ma_device_state_stopped);
|
||||
ma_stop_proc onStop = pDevice->onStop;
|
||||
if (onStop) {
|
||||
onStop(pDevice);
|
||||
}
|
||||
|
||||
return MA_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static ma_result ma_context_uninit__sdl(ma_context* pContext)
|
||||
{
|
||||
MA_ASSERT(pContext != NULL);
|
||||
|
||||
((MA_PFN_SDL_QuitSubSystem)context_sdl.SDL_QuitSubSystem)(MA_SDL_INIT_AUDIO);
|
||||
|
||||
return MA_SUCCESS;
|
||||
}
|
||||
|
||||
static ma_result ma_context_init__sdl(ma_context* pContext, const ma_context_config* pConfig, ma_backend_callbacks* pCallbacks)
|
||||
{
|
||||
MA_ASSERT(pContext != NULL);
|
||||
|
||||
(void)pConfig; /* Unused. */
|
||||
|
||||
context_sdl.SDL_InitSubSystem = (ma_proc)SDL_InitSubSystem;
|
||||
context_sdl.SDL_QuitSubSystem = (ma_proc)SDL_QuitSubSystem;
|
||||
context_sdl.SDL_GetNumAudioDevices = (ma_proc)SDL_GetNumAudioDevices;
|
||||
context_sdl.SDL_GetAudioDeviceName = (ma_proc)SDL_GetAudioDeviceName;
|
||||
context_sdl.SDL_CloseAudioDevice = (ma_proc)SDL_CloseAudioDevice;
|
||||
context_sdl.SDL_OpenAudioDevice = (ma_proc)SDL_OpenAudioDevice;
|
||||
context_sdl.SDL_PauseAudioDevice = (ma_proc)SDL_PauseAudioDevice;
|
||||
|
||||
int resultSDL = ((MA_PFN_SDL_InitSubSystem)context_sdl.SDL_InitSubSystem)(MA_SDL_INIT_AUDIO);
|
||||
if (resultSDL != 0) {
|
||||
return MA_ERROR;
|
||||
}
|
||||
|
||||
pCallbacks->onContextInit = ma_context_init__sdl;
|
||||
pCallbacks->onContextUninit = ma_context_uninit__sdl;
|
||||
pCallbacks->onContextEnumerateDevices = NULL;
|
||||
pCallbacks->onContextGetDeviceInfo = ma_context_get_device_info__sdl;
|
||||
pCallbacks->onDeviceInit = ma_device_init__sdl;
|
||||
pCallbacks->onDeviceUninit = ma_device_uninit__sdl;
|
||||
pCallbacks->onDeviceStart = ma_device_start__sdl;
|
||||
pCallbacks->onDeviceStop = ma_device_stop__sdl;
|
||||
pCallbacks->onDeviceRead = NULL;
|
||||
pCallbacks->onDeviceWrite = NULL;
|
||||
pCallbacks->onDeviceDataLoop = NULL;
|
||||
|
||||
return MA_SUCCESS;
|
||||
}
|
||||
|
|
@ -164,6 +164,7 @@ typedef struct tagBITMAPINFOHEADER {
|
|||
#define MA_FREE RL_FREE
|
||||
|
||||
#if defined(PLATFORM_NX)
|
||||
#define MA_NO_RUNTIME_LINKING
|
||||
#define MA_ENABLE_ONLY_SPECIFIC_BACKENDS
|
||||
#define MA_ENABLE_CUSTOM
|
||||
#endif
|
||||
|
|
@ -176,7 +177,7 @@ typedef struct tagBITMAPINFOHEADER {
|
|||
//#define MA_DEBUG_OUTPUT
|
||||
#include "external/miniaudio.h" // Audio device initialization and management
|
||||
#if defined(PLATFORM_NX)
|
||||
#include "external/miniaudio_sdl.h"
|
||||
#include <miniaudio_audren.h> // Custom audio device for switch
|
||||
#endif
|
||||
#undef PlaySound // Win32 API: windows.h > mmsystem.h defines PlaySound macro
|
||||
|
||||
|
|
@ -432,7 +433,7 @@ void InitAudioDevice(void)
|
|||
ma_backend backends[] = {
|
||||
ma_backend_custom
|
||||
};
|
||||
ctxConfig.custom.onContextInit = ma_context_init__sdl;
|
||||
ctxConfig.custom.onContextInit = ma_context_init__audren;
|
||||
ma_result result = ma_context_init(backends, sizeof(backends)/sizeof(backends[0]), &ctxConfig, &AUDIO.System.context);
|
||||
#else
|
||||
ma_result result = ma_context_init(NULL, 0, &ctxConfig, &AUDIO.System.context);
|
||||
|
|
|
|||
266
src/switch-nx/miniaudio_audren.h
Normal file
266
src/switch-nx/miniaudio_audren.h
Normal file
|
|
@ -0,0 +1,266 @@
|
|||
/******************************************************************************
|
||||
|
||||
Audren Backend
|
||||
|
||||
******************************************************************************/
|
||||
#ifndef miniaudio_audren_h
|
||||
#define miniaudio_audren_h
|
||||
|
||||
#include <stdio.h>
|
||||
#include <malloc.h>
|
||||
#include <stdint.h>
|
||||
#include <switch.h>
|
||||
|
||||
#define LIBNX_AUDREN_BUFFER_COUNT 5
|
||||
|
||||
static const AudioRendererConfig audio_renderer_config =
|
||||
{
|
||||
.output_rate = AudioRendererOutputRate_48kHz,
|
||||
.num_voices = 24,
|
||||
.num_effects = 0,
|
||||
.num_sinks = 1,
|
||||
.num_mix_objs = 1,
|
||||
.num_mix_buffers = 2,
|
||||
};
|
||||
|
||||
static const int sample_rate = 48000;
|
||||
static const int num_channels = 2;
|
||||
static const uint8_t sink_channels[] = { 0, 1 };
|
||||
|
||||
typedef struct
|
||||
{
|
||||
AudioDriver drv;
|
||||
char* mempool;
|
||||
AudioDriverWaveBuf wavebufs[LIBNX_AUDREN_BUFFER_COUNT];
|
||||
AudioDriverWaveBuf* current_wavebuf;
|
||||
char* current_pool_ptr;
|
||||
size_t current_size;
|
||||
size_t buffer_size;
|
||||
size_t samples;
|
||||
Mutex update_lock;
|
||||
} libnx_audren_t;
|
||||
|
||||
static ssize_t libnx_audren_audio_get_free_wavebuf_idx(libnx_audren_t* aud)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < LIBNX_AUDREN_BUFFER_COUNT; i++)
|
||||
{
|
||||
if (aud->wavebufs[i].state == AudioDriverWaveBufState_Free || aud->wavebufs[i].state == AudioDriverWaveBufState_Done)
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static size_t libnx_audren_audio_append(libnx_audren_t* aud, const char *buf, size_t size)
|
||||
{
|
||||
void *dstbuf = NULL;
|
||||
ssize_t free_idx = -1;
|
||||
|
||||
if (!aud->current_wavebuf)
|
||||
{
|
||||
free_idx = libnx_audren_audio_get_free_wavebuf_idx(aud);
|
||||
if (free_idx == -1)
|
||||
return 0;
|
||||
|
||||
aud->current_wavebuf = &aud->wavebufs[free_idx];
|
||||
aud->current_pool_ptr = aud->mempool + (free_idx * aud->buffer_size);
|
||||
aud->current_size = 0;
|
||||
}
|
||||
|
||||
if (size > aud->buffer_size - aud->current_size)
|
||||
size = aud->buffer_size - aud->current_size;
|
||||
|
||||
dstbuf = aud->current_pool_ptr + aud->current_size;
|
||||
memcpy(dstbuf, buf, size);
|
||||
armDCacheFlush(dstbuf, size);
|
||||
|
||||
aud->current_size += size;
|
||||
|
||||
if (aud->current_size == aud->buffer_size)
|
||||
{
|
||||
audrvVoiceAddWaveBuf(&aud->drv, 0, aud->current_wavebuf);
|
||||
|
||||
mutexLock(&aud->update_lock);
|
||||
audrvUpdate(&aud->drv);
|
||||
mutexUnlock(&aud->update_lock);
|
||||
|
||||
if (!audrvVoiceIsPlaying(&aud->drv, 0))
|
||||
{
|
||||
audrvVoiceStart(&aud->drv, 0);
|
||||
}
|
||||
|
||||
aud->current_wavebuf = NULL;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static ma_result ma_device_write__audren(ma_device* pDevice, const void* pFrames, ma_uint32 frameCount, ma_uint32* pFramesWritten)
|
||||
{
|
||||
MA_ASSERT(pDevice != NULL);
|
||||
MA_ASSERT(pFrames != NULL);
|
||||
MA_ASSERT(pDevice->pContext->pUserData != NULL);
|
||||
libnx_audren_t *aud = (libnx_audren_t*)pDevice->pContext->pUserData;
|
||||
|
||||
if (pFramesWritten != NULL)
|
||||
*pFramesWritten = 0;
|
||||
|
||||
if (ma_device_get_state(pDevice) != ma_device_state_started)
|
||||
return MA_DEVICE_NOT_INITIALIZED;
|
||||
|
||||
char *buf = (char*)pFrames;
|
||||
size_t size = frameCount * ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
|
||||
size_t written = 0;
|
||||
|
||||
while (written < size)
|
||||
{
|
||||
written += libnx_audren_audio_append(aud, buf + written, size - written);
|
||||
if (written != size)
|
||||
{
|
||||
mutexLock(&aud->update_lock);
|
||||
audrvUpdate(&aud->drv);
|
||||
mutexUnlock(&aud->update_lock);
|
||||
audrenWaitFrame();
|
||||
}
|
||||
}
|
||||
|
||||
if (written == 0)
|
||||
return MA_IO_ERROR;
|
||||
|
||||
*pFramesWritten = frameCount;
|
||||
|
||||
return MA_SUCCESS;
|
||||
}
|
||||
|
||||
static ma_result ma_device_init__audren(ma_device* pDevice, const ma_device_config* pConfig, ma_device_descriptor* pDescriptorPlayback, ma_device_descriptor* pDescriptorCapture)
|
||||
{
|
||||
MA_ASSERT(pDevice != NULL);
|
||||
MA_ASSERT(pConfig != NULL);
|
||||
MA_ASSERT(pDevice->pContext->pUserData != NULL);
|
||||
libnx_audren_t *aud = (libnx_audren_t*)pDevice->pContext->pUserData;
|
||||
|
||||
if (pConfig->deviceType == ma_device_type_loopback) {
|
||||
return MA_DEVICE_TYPE_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
pDescriptorPlayback->format = ma_format_s16;
|
||||
pDescriptorPlayback->channels = num_channels;
|
||||
pDescriptorPlayback->sampleRate = sample_rate;
|
||||
ma_channel_map_init_standard(ma_standard_channel_map_default, pDescriptorPlayback->channelMap, ma_countof(pDescriptorPlayback->channelMap), pDescriptorPlayback->channels);
|
||||
pDescriptorPlayback->periodSizeInFrames = ma_calculate_buffer_size_in_frames_from_descriptor(pDescriptorPlayback, pDescriptorPlayback->sampleRate, pConfig->performanceProfile);
|
||||
|
||||
aud->buffer_size = pDescriptorPlayback->periodSizeInFrames * ma_get_bytes_per_frame(pDescriptorPlayback->format, pDescriptorPlayback->channels);
|
||||
aud->samples = (aud->buffer_size / num_channels / sizeof(int16_t));
|
||||
aud->current_size = 0;
|
||||
|
||||
size_t mempool_size = (aud->buffer_size * LIBNX_AUDREN_BUFFER_COUNT + (AUDREN_MEMPOOL_ALIGNMENT-1)) &~ (AUDREN_MEMPOOL_ALIGNMENT-1);
|
||||
aud->mempool = memalign(AUDREN_MEMPOOL_ALIGNMENT, mempool_size);
|
||||
|
||||
audrenInitialize(&audio_renderer_config);
|
||||
audrvCreate(&aud->drv, &audio_renderer_config, num_channels);
|
||||
|
||||
unsigned i;
|
||||
for(i = 0; i < LIBNX_AUDREN_BUFFER_COUNT; i++)
|
||||
{
|
||||
aud->wavebufs[i].data_raw = aud->mempool;
|
||||
aud->wavebufs[i].size = mempool_size;
|
||||
aud->wavebufs[i].start_sample_offset = i * aud->samples;
|
||||
aud->wavebufs[i].end_sample_offset = aud->wavebufs[i].start_sample_offset + aud->samples;
|
||||
}
|
||||
aud->current_wavebuf = NULL;
|
||||
|
||||
int mpid = audrvMemPoolAdd(&aud->drv, aud->mempool, mempool_size);
|
||||
audrvMemPoolAttach(&aud->drv, mpid);
|
||||
audrvDeviceSinkAdd(&aud->drv, AUDREN_DEFAULT_DEVICE_NAME, num_channels, sink_channels);
|
||||
audrenStartAudioRenderer();
|
||||
audrvVoiceInit(&aud->drv, 0, num_channels, PcmFormat_Int16, sample_rate);
|
||||
audrvVoiceSetDestinationMix(&aud->drv, 0, AUDREN_FINAL_MIX_ID);
|
||||
|
||||
unsigned j;
|
||||
for(i = 0; i < num_channels; i++)
|
||||
for(j = 0; j < num_channels; j++)
|
||||
audrvVoiceSetMixFactor(&aud->drv, 0, i == j ? 1.0f : 0.0f, i, j);
|
||||
|
||||
mutexInit(&aud->update_lock);
|
||||
|
||||
return MA_SUCCESS;
|
||||
}
|
||||
|
||||
static ma_result ma_context_get_device_info__audren(ma_context* pContext, ma_device_type deviceType, const ma_device_id* pDeviceID, ma_device_info* pDeviceInfo)
|
||||
{
|
||||
MA_ASSERT(pContext != NULL);
|
||||
MA_ASSERT(deviceType == ma_device_type_playback);
|
||||
|
||||
pDeviceInfo->isDefault = MA_TRUE;
|
||||
pDeviceInfo->nativeDataFormatCount = 0;
|
||||
|
||||
ma_device_info_add_native_data_format(pDeviceInfo, ma_format_s16, num_channels, sample_rate, 0);
|
||||
|
||||
return MA_SUCCESS;
|
||||
}
|
||||
|
||||
static ma_result ma_device_start__audren(ma_device* pDevice)
|
||||
{
|
||||
MA_ASSERT(pDevice != NULL);
|
||||
MA_ASSERT(pDevice->pContext->pUserData != NULL);
|
||||
libnx_audren_t *aud = (libnx_audren_t*)pDevice->pContext->pUserData;
|
||||
|
||||
audrvVoiceStart(&aud->drv, 0);
|
||||
|
||||
return MA_SUCCESS;
|
||||
}
|
||||
|
||||
static ma_result ma_device_stop__audren(ma_device* pDevice)
|
||||
{
|
||||
MA_ASSERT(pDevice != NULL);
|
||||
MA_ASSERT(pDevice->pContext->pUserData != NULL);
|
||||
libnx_audren_t *aud = (libnx_audren_t*)pDevice->pContext->pUserData;
|
||||
|
||||
audrvVoiceStop(&aud->drv, 0);
|
||||
|
||||
return MA_SUCCESS;
|
||||
}
|
||||
|
||||
static ma_result ma_device_uninit__audren(ma_device* pDevice)
|
||||
{
|
||||
MA_ASSERT(pDevice != NULL);
|
||||
MA_ASSERT(pDevice->pContext->pUserData != NULL);
|
||||
libnx_audren_t *aud = (libnx_audren_t*)pDevice->pContext->pUserData;
|
||||
|
||||
audrvVoiceStop(&aud->drv, 0);
|
||||
audrvClose(&aud->drv);
|
||||
audrenExit();
|
||||
|
||||
if (aud->mempool)
|
||||
free(aud->mempool);
|
||||
free(aud);
|
||||
|
||||
return MA_SUCCESS;
|
||||
}
|
||||
|
||||
static ma_result ma_context_init__audren(ma_context* pContext, const ma_context_config* pConfig, ma_backend_callbacks* pCallbacks)
|
||||
{
|
||||
MA_ASSERT(pContext != NULL);
|
||||
|
||||
pContext->pUserData = (libnx_audren_t*)calloc(1, sizeof(libnx_audren_t));
|
||||
|
||||
(void)pConfig; /* Unused. */
|
||||
|
||||
pCallbacks->onContextInit = ma_context_init__audren;
|
||||
pCallbacks->onContextUninit = NULL;
|
||||
pCallbacks->onContextEnumerateDevices = NULL;
|
||||
pCallbacks->onContextGetDeviceInfo = ma_context_get_device_info__audren;
|
||||
pCallbacks->onDeviceInit = ma_device_init__audren;
|
||||
pCallbacks->onDeviceUninit = ma_device_uninit__audren;
|
||||
pCallbacks->onDeviceStart = ma_device_start__audren;
|
||||
pCallbacks->onDeviceStop = ma_device_stop__audren;
|
||||
pCallbacks->onDeviceRead = NULL;
|
||||
pCallbacks->onDeviceWrite = ma_device_write__audren;
|
||||
pCallbacks->onDeviceDataLoop = NULL;
|
||||
|
||||
return MA_SUCCESS;
|
||||
}
|
||||
|
||||
#endif
|
||||
Loading…
Reference in New Issue
Block a user