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"
|
||||
|
||||
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
|
||||
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_AudioFormat test_format;
|
||||
|
||||
res = audoutInitialize();
|
||||
if (res != 0) {
|
||||
return SDL_SetError("audoutInitialize failed (0x%x)", res);
|
||||
}
|
||||
|
||||
res = audoutStartAudioOut();
|
||||
if (res != 0) {
|
||||
audoutExit();
|
||||
return SDL_SetError("audoutStartAudioOut failed (0x%x)", res);
|
||||
}
|
||||
Result res;
|
||||
u32 size;
|
||||
int mpid;
|
||||
|
||||
this->hidden = (struct SDL_PrivateAudioData *) SDL_malloc(sizeof(*this->hidden));
|
||||
if (this->hidden == NULL) {
|
||||
|
@ -57,11 +59,24 @@ SWITCHAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
|||
}
|
||||
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);
|
||||
while ((!supported_format) && (test_format)) {
|
||||
if (test_format == AUDIO_S16LSB) {
|
||||
if (test_format == AUDIO_S16SYS) {
|
||||
supported_format = SDL_TRUE;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
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.freq = 48000;
|
||||
this->spec.channels = 2;
|
||||
|
||||
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++) {
|
||||
u32 size = (u32) (this->spec.size + 0xfff) & ~0xfff;
|
||||
this->hidden->buffer[i] = memalign(0x1000, size);
|
||||
memset(this->hidden->buffer[i], 0, size);
|
||||
this->hidden->source_buffer[i].next = NULL;
|
||||
this->hidden->source_buffer[i].buffer = this->hidden->buffer[i];
|
||||
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]);
|
||||
this->hidden->buffer[i].data_raw = this->hidden->pool;
|
||||
this->hidden->buffer[i].size = this->spec.size * 2;
|
||||
this->hidden->buffer[i].start_sample_offset = i * this->spec.samples;
|
||||
this->hidden->buffer[i].end_sample_offset = this->hidden->buffer[i].start_sample_offset + this->spec.samples;
|
||||
this->hidden->buffer_tmp = malloc(this->spec.size);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static void
|
||||
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
|
||||
SWITCHAUDIO_WaitDevice(_THIS)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static Uint8
|
||||
*SWITCHAUDIO_GetDeviceBuf(_THIS)
|
||||
{
|
||||
audoutWaitPlayFinish(&this->hidden->released_buffer,
|
||||
&this->hidden->released_count, U64_MAX);
|
||||
|
||||
return this->hidden->released_buffer->buffer;
|
||||
return this->hidden->buffer_tmp;
|
||||
}
|
||||
|
||||
static void
|
||||
SWITCHAUDIO_CloseDevice(_THIS)
|
||||
{
|
||||
if (this->hidden->buffer[0]) {
|
||||
free(this->hidden->buffer[0]);
|
||||
}
|
||||
if (this->hidden->buffer[1]) {
|
||||
free(this->hidden->buffer[1]);
|
||||
if (this->hidden->audr_driver) {
|
||||
audrvClose(&this->hidden->driver);
|
||||
}
|
||||
|
||||
audoutStopAudioOut();
|
||||
audoutExit();
|
||||
if (this->hidden->audr_device) {
|
||||
audrenExit();
|
||||
}
|
||||
|
||||
if (this->hidden->buffer_tmp) {
|
||||
free(this->hidden->buffer_tmp);
|
||||
}
|
||||
|
||||
SDL_free(this->hidden);
|
||||
}
|
||||
|
|
|
@ -30,11 +30,12 @@
|
|||
|
||||
struct SDL_PrivateAudioData
|
||||
{
|
||||
void *buffer[2];
|
||||
AudioOutBuffer source_buffer[2];
|
||||
AudioOutBuffer *released_buffer;
|
||||
u32 released_count;
|
||||
|
||||
AudioDriver driver;
|
||||
AudioDriverWaveBuf buffer[2];
|
||||
void *buffer_tmp;
|
||||
void *pool;
|
||||
bool audr_device;
|
||||
bool audr_driver;
|
||||
};
|
||||
|
||||
#endif /* SDL_switchaudio_h_ */
|
||||
|
|
Loading…
Reference in New Issue