mirror of https://github.com/encounter/SDL.git
switch: use audren audio
fix suspend, allow freqs other than 48khz
This commit is contained in:
parent
0c22a3c059
commit
12f161236f
|
@ -33,23 +33,25 @@
|
||||||
|
|
||||||
#include "SDL_switchaudio.h"
|
#include "SDL_switchaudio.h"
|
||||||
|
|
||||||
|
static const AudioRendererConfig arConfig =
|
||||||
|
{
|
||||||
|
.output_rate = AudioRendererOutputRate_48kHz,
|
||||||
|
.num_voices = 24,
|
||||||
|
.num_effects = 0,
|
||||||
|
.num_sinks = 1,
|
||||||
|
.num_mix_objs = 1,
|
||||||
|
.num_mix_buffers = 2,
|
||||||
|
};
|
||||||
|
|
||||||
static int
|
static int
|
||||||
SWITCHAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
SWITCHAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
||||||
{
|
{
|
||||||
Result res;
|
static const u8 sink_channels[] = {0, 1};
|
||||||
SDL_bool supported_format = SDL_FALSE;
|
SDL_bool supported_format = SDL_FALSE;
|
||||||
SDL_AudioFormat test_format;
|
SDL_AudioFormat test_format;
|
||||||
|
Result res;
|
||||||
res = audoutInitialize();
|
u32 size;
|
||||||
if (res != 0) {
|
int mpid;
|
||||||
return SDL_SetError("audoutInitialize failed (0x%x)", res);
|
|
||||||
}
|
|
||||||
|
|
||||||
res = audoutStartAudioOut();
|
|
||||||
if (res != 0) {
|
|
||||||
audoutExit();
|
|
||||||
return SDL_SetError("audoutStartAudioOut failed (0x%x)", res);
|
|
||||||
}
|
|
||||||
|
|
||||||
this->hidden = (struct SDL_PrivateAudioData *) SDL_malloc(sizeof(*this->hidden));
|
this->hidden = (struct SDL_PrivateAudioData *) SDL_malloc(sizeof(*this->hidden));
|
||||||
if (this->hidden == NULL) {
|
if (this->hidden == NULL) {
|
||||||
|
@ -57,11 +59,24 @@ SWITCHAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
||||||
}
|
}
|
||||||
SDL_zerop(this->hidden);
|
SDL_zerop(this->hidden);
|
||||||
|
|
||||||
|
res = audrenInitialize(&arConfig);
|
||||||
|
if (R_FAILED(res)) {
|
||||||
|
return SDL_SetError("audrenInitialize failed (0x%x)", res);
|
||||||
|
}
|
||||||
|
this->hidden->audr_device = true;
|
||||||
|
|
||||||
|
res = audrvCreate(&this->hidden->driver, &arConfig, 2);
|
||||||
|
if (R_FAILED(res)) {
|
||||||
|
return SDL_SetError("audrvCreate failed (0x%x)", res);
|
||||||
|
}
|
||||||
|
this->hidden->audr_driver = true;
|
||||||
|
|
||||||
test_format = SDL_FirstAudioFormat(this->spec.format);
|
test_format = SDL_FirstAudioFormat(this->spec.format);
|
||||||
while ((!supported_format) && (test_format)) {
|
while ((!supported_format) && (test_format)) {
|
||||||
if (test_format == AUDIO_S16LSB) {
|
if (test_format == AUDIO_S16SYS) {
|
||||||
supported_format = SDL_TRUE;
|
supported_format = SDL_TRUE;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
test_format = SDL_NextAudioFormat();
|
test_format = SDL_NextAudioFormat();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -70,60 +85,116 @@ SWITCHAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
||||||
}
|
}
|
||||||
|
|
||||||
this->spec.format = test_format;
|
this->spec.format = test_format;
|
||||||
this->spec.freq = 48000;
|
|
||||||
this->spec.channels = 2;
|
|
||||||
|
|
||||||
SDL_CalculateAudioSpec(&this->spec);
|
SDL_CalculateAudioSpec(&this->spec);
|
||||||
|
|
||||||
|
size = (u32) ((this->spec.size * 2) + 0xfff) & ~0xfff;
|
||||||
|
this->hidden->pool = memalign(0x1000, size);
|
||||||
for (int i = 0; i < 2; i++) {
|
for (int i = 0; i < 2; i++) {
|
||||||
u32 size = (u32) (this->spec.size + 0xfff) & ~0xfff;
|
this->hidden->buffer[i].data_raw = this->hidden->pool;
|
||||||
this->hidden->buffer[i] = memalign(0x1000, size);
|
this->hidden->buffer[i].size = this->spec.size * 2;
|
||||||
memset(this->hidden->buffer[i], 0, size);
|
this->hidden->buffer[i].start_sample_offset = i * this->spec.samples;
|
||||||
this->hidden->source_buffer[i].next = NULL;
|
this->hidden->buffer[i].end_sample_offset = this->hidden->buffer[i].start_sample_offset + this->spec.samples;
|
||||||
this->hidden->source_buffer[i].buffer = this->hidden->buffer[i];
|
this->hidden->buffer_tmp = malloc(this->spec.size);
|
||||||
this->hidden->source_buffer[i].buffer_size =
|
|
||||||
(u64) this->spec.size / this->spec.channels / 4;
|
|
||||||
this->hidden->source_buffer[i].data_size = (u64) this->spec.size;
|
|
||||||
this->hidden->source_buffer[i].data_offset = (u64) 0;
|
|
||||||
audoutAppendAudioOutBuffer(&this->hidden->source_buffer[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mpid = audrvMemPoolAdd(&this->hidden->driver, this->hidden->pool, size);
|
||||||
|
audrvMemPoolAttach(&this->hidden->driver, mpid);
|
||||||
|
|
||||||
|
audrvDeviceSinkAdd(&this->hidden->driver, AUDREN_DEFAULT_DEVICE_NAME, 2, sink_channels);
|
||||||
|
|
||||||
|
res = audrenStartAudioRenderer();
|
||||||
|
if (R_FAILED(res)) {
|
||||||
|
return SDL_SetError("audrenStartAudioRenderer failed (0x%x)", res);
|
||||||
|
}
|
||||||
|
|
||||||
|
audrvVoiceInit(&this->hidden->driver, 0, this->spec.channels, PcmFormat_Int16, this->spec.freq);
|
||||||
|
audrvVoiceSetDestinationMix(&this->hidden->driver, 0, AUDREN_FINAL_MIX_ID);
|
||||||
|
if (this->spec.channels == 1) {
|
||||||
|
audrvVoiceSetMixFactor(&this->hidden->driver, 0, 1.0f, 0, 0);
|
||||||
|
audrvVoiceSetMixFactor(&this->hidden->driver, 0, 1.0f, 0, 1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
audrvVoiceSetMixFactor(&this->hidden->driver, 0, 1.0f, 0, 0);
|
||||||
|
audrvVoiceSetMixFactor(&this->hidden->driver, 0, 0.0f, 0, 1);
|
||||||
|
audrvVoiceSetMixFactor(&this->hidden->driver, 0, 0.0f, 1, 0);
|
||||||
|
audrvVoiceSetMixFactor(&this->hidden->driver, 0, 1.0f, 1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
audrvVoiceStart(&this->hidden->driver, 0);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
SWITCHAUDIO_PlayDevice(_THIS)
|
SWITCHAUDIO_PlayDevice(_THIS)
|
||||||
{
|
{
|
||||||
audoutAppendAudioOutBuffer(this->hidden->released_buffer);
|
int current = -1;
|
||||||
|
for (int i = 0; i < 2; i++) {
|
||||||
|
if (this->hidden->buffer[i].state == AudioDriverWaveBufState_Free
|
||||||
|
|| this->hidden->buffer[i].state == AudioDriverWaveBufState_Done) {
|
||||||
|
current = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current >= 0) {
|
||||||
|
Uint8 *ptr = (Uint8 *) (this->hidden->pool + (current * this->spec.size));
|
||||||
|
memcpy(ptr, this->hidden->buffer_tmp, this->spec.size);
|
||||||
|
armDCacheFlush(ptr, this->spec.size);
|
||||||
|
audrvVoiceAddWaveBuf(&this->hidden->driver, 0, &this->hidden->buffer[current]);
|
||||||
|
}
|
||||||
|
else if (!audrvVoiceIsPlaying(&this->hidden->driver, 0)) {
|
||||||
|
audrvVoiceStart(&this->hidden->driver, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
audrvUpdate(&this->hidden->driver);
|
||||||
|
|
||||||
|
if (current >= 0) {
|
||||||
|
while (this->hidden->buffer[current].state != AudioDriverWaveBufState_Playing) {
|
||||||
|
audrvUpdate(&this->hidden->driver);
|
||||||
|
audrenWaitFrame();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
current = -1;
|
||||||
|
for (int i = 0; i < 2; i++) {
|
||||||
|
if (this->hidden->buffer[i].state == AudioDriverWaveBufState_Playing) {
|
||||||
|
current = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (this->hidden->buffer[current].state == AudioDriverWaveBufState_Playing) {
|
||||||
|
audrvUpdate(&this->hidden->driver);
|
||||||
|
audrenWaitFrame();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
SWITCHAUDIO_WaitDevice(_THIS)
|
SWITCHAUDIO_WaitDevice(_THIS)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static Uint8
|
static Uint8
|
||||||
*SWITCHAUDIO_GetDeviceBuf(_THIS)
|
*SWITCHAUDIO_GetDeviceBuf(_THIS)
|
||||||
{
|
{
|
||||||
audoutWaitPlayFinish(&this->hidden->released_buffer,
|
return this->hidden->buffer_tmp;
|
||||||
&this->hidden->released_count, U64_MAX);
|
|
||||||
|
|
||||||
return this->hidden->released_buffer->buffer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
SWITCHAUDIO_CloseDevice(_THIS)
|
SWITCHAUDIO_CloseDevice(_THIS)
|
||||||
{
|
{
|
||||||
if (this->hidden->buffer[0]) {
|
if (this->hidden->audr_driver) {
|
||||||
free(this->hidden->buffer[0]);
|
audrvClose(&this->hidden->driver);
|
||||||
}
|
|
||||||
if (this->hidden->buffer[1]) {
|
|
||||||
free(this->hidden->buffer[1]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
audoutStopAudioOut();
|
if (this->hidden->audr_device) {
|
||||||
audoutExit();
|
audrenExit();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->hidden->buffer_tmp) {
|
||||||
|
free(this->hidden->buffer_tmp);
|
||||||
|
}
|
||||||
|
|
||||||
SDL_free(this->hidden);
|
SDL_free(this->hidden);
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,11 +30,12 @@
|
||||||
|
|
||||||
struct SDL_PrivateAudioData
|
struct SDL_PrivateAudioData
|
||||||
{
|
{
|
||||||
void *buffer[2];
|
AudioDriver driver;
|
||||||
AudioOutBuffer source_buffer[2];
|
AudioDriverWaveBuf buffer[2];
|
||||||
AudioOutBuffer *released_buffer;
|
void *buffer_tmp;
|
||||||
u32 released_count;
|
void *pool;
|
||||||
|
bool audr_device;
|
||||||
|
bool audr_driver;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* SDL_switchaudio_h_ */
|
#endif /* SDL_switchaudio_h_ */
|
||||||
|
|
Loading…
Reference in New Issue