Skip to content

Commit 78899b6

Browse files
authored
Fix regression with stuttery audio after suspend (#64)
This reverts the change from audren to audout pending further investigation of the audio issues after suspend/resume.
1 parent 371ccb8 commit 78899b6

File tree

4 files changed

+128
-98
lines changed

4 files changed

+128
-98
lines changed

src/audio/SDL_audio.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ static const AudioBootStrap *const bootstrap[] = {
112112
&EMSCRIPTENAUDIO_bootstrap,
113113
#endif
114114
#if SDL_AUDIO_DRIVER_SWITCH
115-
&SWITCHAUDIOOUT_bootstrap,
115+
&SWITCHAUDIO_bootstrap,
116116
#endif
117117
#if SDL_AUDIO_DRIVER_JACK
118118
&JACK_bootstrap,

src/audio/SDL_sysaudio.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ extern AudioBootStrap VITAAUD_bootstrap;
209209
extern AudioBootStrap N3DSAUDIO_bootstrap;
210210
extern AudioBootStrap EMSCRIPTENAUDIO_bootstrap;
211211
extern AudioBootStrap OS2AUDIO_bootstrap;
212-
extern AudioBootStrap SWITCHAUDIOOUT_bootstrap;
212+
extern AudioBootStrap SWITCHAUDIO_bootstrap;
213213

214214
#endif /* SDL_sysaudio_h_ */
215215

src/audio/switch/SDL_switchaudio.c

Lines changed: 120 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -33,130 +33,167 @@
3333

3434
#include "SDL_switchaudio.h"
3535

36+
static const AudioRendererConfig arConfig =
37+
{
38+
.output_rate = AudioRendererOutputRate_48kHz,
39+
.num_voices = 24,
40+
.num_effects = 0,
41+
.num_sinks = 1,
42+
.num_mix_objs = 1,
43+
.num_mix_buffers = 2,
44+
};
45+
3646
static int
3747
SWITCHAUDIO_OpenDevice(_THIS, const char *devname)
3848
{
49+
static const u8 sink_channels[] = {0, 1};
50+
SDL_bool supported_format = SDL_FALSE;
51+
SDL_AudioFormat test_format;
3952
Result res;
40-
PcmFormat fmt;
41-
int mixlen, aligned_size, i;
53+
u32 size;
54+
int mpid;
4255

4356
this->hidden = (struct SDL_PrivateAudioData *) SDL_malloc(sizeof(*this->hidden));
4457
if (this->hidden == NULL) {
4558
return SDL_OutOfMemory();
4659
}
4760
SDL_zerop(this->hidden);
4861

49-
res = audoutInitialize();
62+
res = audrenInitialize(&arConfig);
5063
if (R_FAILED(res)) {
51-
SDL_free(this->hidden);
52-
this->hidden = NULL;
53-
return SDL_SetError("audoutInitialize failed (0x%x)", res);
54-
}
55-
56-
fmt = audoutGetPcmFormat();
57-
switch (fmt) {
58-
case PcmFormat_Invalid:
59-
SDL_free(this->hidden);
60-
this->hidden = NULL;
61-
return SDL_SetError("audoutGetPcmFormat returned invalid value (0x%x)", (int)fmt);
62-
case PcmFormat_Int8:
63-
this->spec.format = AUDIO_S8;
64-
break;
65-
case PcmFormat_Int16:
66-
this->spec.format = AUDIO_S16SYS;
67-
break;
68-
case PcmFormat_Int32:
69-
this->spec.format = AUDIO_S32SYS;
70-
break;
71-
case PcmFormat_Float:
72-
this->spec.format = AUDIO_F32SYS;
73-
break;
74-
case PcmFormat_Int24:
75-
case PcmFormat_Adpcm:
76-
SDL_free(this->hidden);
77-
this->hidden = NULL;
78-
return SDL_SetError("audoutGetPcmFormat returned unsupported sample format (0x%x)", (int)fmt);
79-
break;
80-
}
81-
82-
this->spec.freq = (int)audoutGetSampleRate();
83-
this->spec.channels = audoutGetChannelCount();
64+
return SDL_SetError("audrenInitialize failed (0x%x)", res);
65+
}
66+
this->hidden->audr_device = true;
8467

85-
SDL_CalculateAudioSpec(&this->spec);
68+
res = audrvCreate(&this->hidden->driver, &arConfig, 2);
69+
if (R_FAILED(res)) {
70+
return SDL_SetError("audrvCreate failed (0x%x)", res);
71+
}
72+
this->hidden->audr_driver = true;
73+
74+
test_format = SDL_FirstAudioFormat(this->spec.format);
75+
while ((!supported_format) && (test_format)) {
76+
if (test_format == AUDIO_S16SYS) {
77+
supported_format = SDL_TRUE;
78+
}
79+
else {
80+
test_format = SDL_NextAudioFormat();
81+
}
82+
}
83+
if (!supported_format) {
84+
return SDL_SetError("Unsupported audio format");
85+
}
8686

87-
aligned_size = (this->spec.size + 0xfff) & ~0xfff;
88-
mixlen = aligned_size * NUM_BUFFERS;
87+
this->spec.format = test_format;
88+
SDL_CalculateAudioSpec(&this->spec);
8989

90-
this->hidden->rawbuf = memalign(0x1000, mixlen);
91-
if (this->hidden->rawbuf == NULL) {
92-
SDL_free(this->hidden);
93-
this->hidden = NULL;
94-
return SDL_SetError("Couldn't allocate mixing buffer");
90+
size = (u32) ((this->spec.size * 2) + 0xfff) & ~0xfff;
91+
this->hidden->pool = memalign(0x1000, size);
92+
for (int i = 0; i < 2; i++) {
93+
this->hidden->buffer[i].data_raw = this->hidden->pool;
94+
this->hidden->buffer[i].size = this->spec.size * 2;
95+
this->hidden->buffer[i].start_sample_offset = i * this->spec.samples;
96+
this->hidden->buffer[i].end_sample_offset = this->hidden->buffer[i].start_sample_offset + this->spec.samples;
97+
this->hidden->buffer_tmp = malloc(this->spec.size);
9598
}
9699

97-
SDL_memset(this->hidden->rawbuf, 0, mixlen);
98-
for (i = 0; i < NUM_BUFFERS; i++) {
99-
this->hidden->out_buffers[i] = &this->hidden->rawbuf[i * aligned_size];
100-
this->hidden->buffer[i].next = NULL;
101-
this->hidden->buffer[i].buffer = this->hidden->out_buffers[i];
102-
this->hidden->buffer[i].buffer_size = aligned_size;
103-
this->hidden->buffer[i].data_size = this->spec.size;
104-
this->hidden->buffer[i].data_offset = 0;
105-
}
100+
mpid = audrvMemPoolAdd(&this->hidden->driver, this->hidden->pool, size);
101+
audrvMemPoolAttach(&this->hidden->driver, mpid);
106102

107-
this->hidden->cur_buffer = this->hidden->next_buffer;
108-
this->hidden->next_buffer = (this->hidden->next_buffer + 1) % NUM_BUFFERS;
103+
audrvDeviceSinkAdd(&this->hidden->driver, AUDREN_DEFAULT_DEVICE_NAME, 2, sink_channels);
109104

110-
res = audoutAppendAudioOutBuffer(&this->hidden->buffer[this->hidden->cur_buffer]);
105+
res = audrenStartAudioRenderer();
111106
if (R_FAILED(res)) {
112-
free(this->hidden->rawbuf);
113-
this->hidden->rawbuf = NULL;
114-
SDL_free(this->hidden);
115-
this->hidden = NULL;
116-
return SDL_SetError("audoutAppendAudioOutBuffer failed (0x%x)", res);
107+
return SDL_SetError("audrenStartAudioRenderer failed (0x%x)", res);
117108
}
118109

119-
res = audoutStartAudioOut();
120-
if (R_FAILED(res)) {
121-
free(this->hidden->rawbuf);
122-
this->hidden->rawbuf = NULL;
123-
SDL_free(this->hidden);
124-
this->hidden = NULL;
125-
return SDL_SetError("audoutStartAudioOut failed (0x%x)", res);
110+
audrvVoiceInit(&this->hidden->driver, 0, this->spec.channels, PcmFormat_Int16, this->spec.freq);
111+
audrvVoiceSetDestinationMix(&this->hidden->driver, 0, AUDREN_FINAL_MIX_ID);
112+
if (this->spec.channels == 1) {
113+
audrvVoiceSetMixFactor(&this->hidden->driver, 0, 1.0f, 0, 0);
114+
audrvVoiceSetMixFactor(&this->hidden->driver, 0, 1.0f, 0, 1);
115+
}
116+
else {
117+
audrvVoiceSetMixFactor(&this->hidden->driver, 0, 1.0f, 0, 0);
118+
audrvVoiceSetMixFactor(&this->hidden->driver, 0, 0.0f, 0, 1);
119+
audrvVoiceSetMixFactor(&this->hidden->driver, 0, 0.0f, 1, 0);
120+
audrvVoiceSetMixFactor(&this->hidden->driver, 0, 1.0f, 1, 1);
126121
}
127122

123+
audrvVoiceStart(&this->hidden->driver, 0);
124+
128125
return 0;
129126
}
130127

131128
static void
132129
SWITCHAUDIO_PlayDevice(_THIS)
133130
{
134-
this->hidden->cur_buffer = this->hidden->next_buffer;
135-
audoutAppendAudioOutBuffer(&this->hidden->buffer[this->hidden->cur_buffer]);
136-
this->hidden->next_buffer = (this->hidden->next_buffer + 1) % NUM_BUFFERS;
131+
int current = -1;
132+
for (int i = 0; i < 2; i++) {
133+
if (this->hidden->buffer[i].state == AudioDriverWaveBufState_Free
134+
|| this->hidden->buffer[i].state == AudioDriverWaveBufState_Done) {
135+
current = i;
136+
break;
137+
}
138+
}
139+
140+
if (current >= 0) {
141+
Uint8 *ptr = (Uint8 *) (this->hidden->pool + (current * this->spec.size));
142+
memcpy(ptr, this->hidden->buffer_tmp, this->spec.size);
143+
armDCacheFlush(ptr, this->spec.size);
144+
audrvVoiceAddWaveBuf(&this->hidden->driver, 0, &this->hidden->buffer[current]);
145+
}
146+
else if (!audrvVoiceIsPlaying(&this->hidden->driver, 0)) {
147+
audrvVoiceStart(&this->hidden->driver, 0);
148+
}
149+
150+
audrvUpdate(&this->hidden->driver);
151+
152+
if (current >= 0) {
153+
while (this->hidden->buffer[current].state != AudioDriverWaveBufState_Playing) {
154+
audrvUpdate(&this->hidden->driver);
155+
audrenWaitFrame();
156+
}
157+
}
158+
else {
159+
current = -1;
160+
for (int i = 0; i < 2; i++) {
161+
if (this->hidden->buffer[i].state == AudioDriverWaveBufState_Playing) {
162+
current = i;
163+
break;
164+
}
165+
}
166+
while (this->hidden->buffer[current].state == AudioDriverWaveBufState_Playing) {
167+
audrvUpdate(&this->hidden->driver);
168+
audrenWaitFrame();
169+
}
170+
}
137171
}
138172

139173
static void
140174
SWITCHAUDIO_WaitDevice(_THIS)
141175
{
142-
audoutWaitPlayFinish(&this->hidden->released_out_buffer, &this->hidden->released_out_count, UINT64_MAX);
143176
}
144177

145178
static Uint8
146179
*SWITCHAUDIO_GetDeviceBuf(_THIS)
147180
{
148-
return this->hidden->out_buffers[this->hidden->next_buffer];
181+
return this->hidden->buffer_tmp;
149182
}
150183

151184
static void
152185
SWITCHAUDIO_CloseDevice(_THIS)
153186
{
154-
audoutStopAudioOut();
155-
audoutExit();
187+
if (this->hidden->audr_driver) {
188+
audrvClose(&this->hidden->driver);
189+
}
156190

157-
if (this->hidden->rawbuf) {
158-
free(this->hidden->rawbuf);
159-
this->hidden->rawbuf = NULL;
191+
if (this->hidden->audr_device) {
192+
audrenExit();
193+
}
194+
195+
if (this->hidden->buffer_tmp) {
196+
free(this->hidden->buffer_tmp);
160197
}
161198

162199
SDL_free(this->hidden);
@@ -165,7 +202,7 @@ SWITCHAUDIO_CloseDevice(_THIS)
165202
static void
166203
SWITCHAUDIO_ThreadInit(_THIS)
167204
{
168-
(void)this;
205+
169206
}
170207

171208
static SDL_bool
@@ -178,13 +215,13 @@ SWITCHAUDIO_Init(SDL_AudioDriverImpl *impl)
178215
impl->CloseDevice = SWITCHAUDIO_CloseDevice;
179216
impl->ThreadInit = SWITCHAUDIO_ThreadInit;
180217

181-
impl->OnlyHasDefaultOutputDevice = SDL_TRUE;
218+
impl->OnlyHasDefaultOutputDevice = 1;
182219

183-
return SDL_TRUE;
220+
return 1;
184221
}
185222

186-
AudioBootStrap SWITCHAUDIOOUT_bootstrap = {
187-
"switchout", "Nintendo Switch audio out driver", SWITCHAUDIO_Init, SDL_FALSE
223+
AudioBootStrap SWITCHAUDIO_bootstrap = {
224+
"switch", "Nintendo Switch audio driver", SWITCHAUDIO_Init, 0
188225
};
189226

190227
#endif /* SDL_AUDIO_DRIVER_SWITCH */

src/audio/switch/SDL_switchaudio.h

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -28,21 +28,14 @@
2828
/* Hidden "this" pointer for the audio functions */
2929
#define _THIS SDL_AudioDevice *this
3030

31-
#define NUM_BUFFERS 2
32-
3331
struct SDL_PrivateAudioData
3432
{
35-
AudioOutBuffer buffer[NUM_BUFFERS];
36-
AudioOutBuffer *released_out_buffer;
37-
u32 released_out_count;
38-
/* The raw allocated mixing buffer. */
39-
Uint8 *rawbuf;
40-
/* Individual mixing buffers. */
41-
void *out_buffers[NUM_BUFFERS];
42-
/* Index of the next available mixing buffer. */
43-
int next_buffer;
44-
/* Currently playing buffer */
45-
int cur_buffer;
33+
AudioDriver driver;
34+
AudioDriverWaveBuf buffer[2];
35+
void *buffer_tmp;
36+
void *pool;
37+
bool audr_device;
38+
bool audr_driver;
4639
};
4740

4841
#endif /* SDL_switchaudio_h_ */

0 commit comments

Comments
 (0)