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+
3646static int
3747SWITCHAUDIO_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
131128static void
132129SWITCHAUDIO_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
139173static void
140174SWITCHAUDIO_WaitDevice (_THIS )
141175{
142- audoutWaitPlayFinish (& this -> hidden -> released_out_buffer , & this -> hidden -> released_out_count , UINT64_MAX );
143176}
144177
145178static Uint8
146179* SWITCHAUDIO_GetDeviceBuf (_THIS )
147180{
148- return this -> hidden -> out_buffers [ this -> hidden -> next_buffer ] ;
181+ return this -> hidden -> buffer_tmp ;
149182}
150183
151184static void
152185SWITCHAUDIO_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)
165202static void
166203SWITCHAUDIO_ThreadInit (_THIS )
167204{
168- ( void ) this ;
205+
169206}
170207
171208static 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 */
0 commit comments