Merge pull request #2 from lucaskyer/miniaudio_audren_slim
Replace SDL by native libnx audio driver
This commit is contained in:
commit
a6132edc1b
|
|
@ -110,7 +110,7 @@ raylib is also available via multiple [package managers](https://github.com/rays
|
|||
- [Working for Android](https://github.com/raysan5/raylib/wiki/Working-for-Android)
|
||||
- [Working for Web (HTML5)](https://github.com/raysan5/raylib/wiki/Working-for-Web-(HTML5))
|
||||
- [Working anywhere with CMake](https://github.com/raysan5/raylib/wiki/Working-with-CMake)
|
||||
|
||||
|
||||
*Note that Wiki is open for edit, if you find some issue while building raylib for your target platform, feel free to edit the Wiki or open and issue related to it.*
|
||||
|
||||
#### Setup raylib with multiple IDEs
|
||||
|
|
|
|||
|
|
@ -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