Mercurial > sdl-ios-xcode
comparison src/audio/nds/SDL_ndsaudio.c @ 3976:8582c6a5ca16 SDL-1.2
Added initial support for Nintendo DS, based on the work by Troy Davis (GPF)
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Mon, 25 Jun 2007 00:50:20 +0000 |
parents | |
children | a1b03ba2fcd0 |
comparison
equal
deleted
inserted
replaced
3975:e85e65aec22f | 3976:8582c6a5ca16 |
---|---|
1 /* | |
2 SDL - Simple DirectMedia Layer | |
3 Copyright (C) 1997-2006 Sam Lantinga | |
4 | |
5 This library is free software; you can redistribute it and/or | |
6 modify it under the terms of the GNU Lesser General Public | |
7 License as published by the Free Software Foundation; either | |
8 version 2.1 of the License, or (at your option) any later version. | |
9 | |
10 This library is distributed in the hope that it will be useful, | |
11 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 Lesser General Public License for more details. | |
14 | |
15 You should have received a copy of the GNU Lesser General Public | |
16 License along with this library; if not, write to the Free Software | |
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
18 | |
19 Sam Lantinga | |
20 slouken@libsdl.org | |
21 */ | |
22 #include "SDL_config.h" | |
23 | |
24 /* Allow access to a raw mixing buffer */ | |
25 #include <nds.h> | |
26 #include "SDL.h" | |
27 #include "SDL_endian.h" | |
28 #include "SDL_timer.h" | |
29 #include "SDL_audio.h" | |
30 #include "../SDL_audiomem.h" | |
31 #include "../SDL_audio_c.h" | |
32 #include "SDL_ndsaudio.h" | |
33 #include "soundcommon.h" | |
34 | |
35 | |
36 /* Audio driver functions */ | |
37 static int NDS_OpenAudio(_THIS, SDL_AudioSpec *spec); | |
38 static void NDS_WaitAudio(_THIS); | |
39 static void NDS_PlayAudio(_THIS); | |
40 static Uint8 *NDS_GetAudioBuf(_THIS); | |
41 static void NDS_CloseAudio(_THIS); | |
42 | |
43 /* Audio driver bootstrap functions */ | |
44 | |
45 u32 framecounter = 0,soundoffset = 0; | |
46 static SDL_AudioDevice *sdl_nds_audiodevice; | |
47 | |
48 //void SoundMixCallback(void *stream,u32 size) | |
49 //{ | |
50 // //printf("SoundMixCallback\n"); | |
51 // | |
52 // Uint8 *buffer; | |
53 // | |
54 // buffer = sdl_nds_audiodevice->hidden->mixbuf; | |
55 // memset(buffer, sdl_nds_audiodevice->spec.silence, size); | |
56 // | |
57 // if (!sdl_nds_audiodevice->paused){ | |
58 // | |
59 // | |
60 // //if (sdl_nds_audiodevice->convert.needed) { | |
61 // // int silence; | |
62 // | |
63 // // if (sdl_nds_audiodevice->convert.src_format == AUDIO_U8 ) { | |
64 // // silence = 0x80; | |
65 // // } else { | |
66 // // silence = 0; | |
67 // // } | |
68 // // memset(sdl_nds_audiodevice->convert.buf, silence, sdl_nds_audiodevice->convert.len); | |
69 // // sdl_nds_audiodevice->spec.callback(sdl_nds_audiodevice->spec.userdata, | |
70 // // (Uint8 *)sdl_nds_audiodevice->convert.buf,sdl_nds_audiodevice->convert.len); | |
71 // // SDL_ConvertAudio(&sdl_nds_audiodevice->convert); | |
72 // // memcpy(buffer, sdl_nds_audiodevice->convert.buf, sdl_nds_audiodevice->convert.len_cvt); | |
73 // //} else | |
74 // { | |
75 // sdl_nds_audiodevice->spec.callback(sdl_nds_audiodevice->spec.userdata, buffer, size); | |
76 // //memcpy((Sint16 *)stream,buffer, size); | |
77 // } | |
78 // | |
79 // } | |
80 // | |
81 // if(soundsystem->format == 8) | |
82 // { | |
83 // int i; | |
84 // s32 *buffer32 = (s32 *)buffer; | |
85 // s32 *stream32 = (s32 *)stream; | |
86 // for(i=0;i<size/4;i++){ *stream32++ = buffer32[i] ^ 0x80808080;} | |
87 // //for(i = 0; i < size; i++) | |
88 // // ((s8*)stream)[i]=(buffer[i]^0x80); | |
89 // } | |
90 // else | |
91 // { | |
92 // int i; | |
93 // for(i = 0; i < size; i++){ | |
94 // //((short*)stream)[i] =(short)buffer[i] << 8; // sound 8bit ---> buffer 16bit | |
95 // //if (buffer[i] &0x80) | |
96 // //((Sint16*)stream)[i] = 0xff00 | buffer[i]; | |
97 // ((Sint16*)stream)[i] = (buffer[i] - 128) << 8; | |
98 // | |
99 // //else | |
100 // // ((Sint16*)stream)[i] = buffer[i]; | |
101 // } | |
102 // //register signed char *pSrc =buffer; | |
103 // //register short *pDest =stream; | |
104 // //int x; | |
105 // // for (x=size; x>0; x--) | |
106 // // { | |
107 // // register short temp = (((short)*pSrc)-128)<<8; | |
108 // // pSrc++; | |
109 // // *pDest++ = temp; | |
110 // // } | |
111 // | |
112 // //memcpy((Sint16 *)stream,buffer, size); | |
113 // } | |
114 //} | |
115 | |
116 void SoundMixCallback(void *stream,u32 len) | |
117 { | |
118 SDL_AudioDevice *audio = (SDL_AudioDevice *)sdl_nds_audiodevice; | |
119 | |
120 /* Silence the buffer, since it's ours */ | |
121 SDL_memset(stream, audio->spec.silence, len); | |
122 | |
123 /* Only do soemthing if audio is enabled */ | |
124 if ( ! audio->enabled ) | |
125 return; | |
126 | |
127 if ( ! audio->paused ) { | |
128 if ( audio->convert.needed ) { | |
129 //fprintf(stderr,"converting audio\n"); | |
130 SDL_mutexP(audio->mixer_lock); | |
131 (*audio->spec.callback)(audio->spec.userdata, | |
132 (Uint8 *)audio->convert.buf,audio->convert.len); | |
133 SDL_mutexV(audio->mixer_lock); | |
134 SDL_ConvertAudio(&audio->convert); | |
135 SDL_memcpy(stream,audio->convert.buf,audio->convert.len_cvt); | |
136 } else { | |
137 SDL_mutexP(audio->mixer_lock); | |
138 (*audio->spec.callback)(audio->spec.userdata, | |
139 (Uint8 *)stream, len); | |
140 SDL_mutexV(audio->mixer_lock); | |
141 } | |
142 } | |
143 return; | |
144 } | |
145 void MixSound(void) | |
146 { | |
147 int remain; | |
148 | |
149 if(soundsystem->format == 8) | |
150 { | |
151 if((soundsystem->soundcursor + soundsystem->numsamples) > soundsystem->buffersize) | |
152 { | |
153 SoundMixCallback(&soundsystem->mixbuffer[soundsystem->soundcursor],soundsystem->buffersize - soundsystem->soundcursor); | |
154 remain = soundsystem->numsamples - (soundsystem->buffersize - soundsystem->soundcursor); | |
155 SoundMixCallback(soundsystem->mixbuffer,remain); | |
156 } | |
157 else | |
158 { | |
159 SoundMixCallback(&soundsystem->mixbuffer[soundsystem->soundcursor],soundsystem->numsamples); | |
160 } | |
161 } | |
162 else | |
163 { | |
164 if((soundsystem->soundcursor + soundsystem->numsamples) > (soundsystem->buffersize >> 1)) | |
165 { | |
166 SoundMixCallback(&soundsystem->mixbuffer[soundsystem->soundcursor << 1],(soundsystem->buffersize >> 1) - soundsystem->soundcursor); | |
167 remain = soundsystem->numsamples - ((soundsystem->buffersize >> 1) - soundsystem->soundcursor); | |
168 SoundMixCallback(soundsystem->mixbuffer,remain); | |
169 } | |
170 else | |
171 { | |
172 SoundMixCallback(&soundsystem->mixbuffer[soundsystem->soundcursor << 1],soundsystem->numsamples); | |
173 } | |
174 } | |
175 } | |
176 | |
177 void InterruptHandler(void) | |
178 { | |
179 framecounter++; | |
180 } | |
181 void FiFoHandler(void) | |
182 { | |
183 u32 command; | |
184 while ( !(REG_IPC_FIFO_CR & (IPC_FIFO_RECV_EMPTY)) ) | |
185 { | |
186 command = REG_IPC_FIFO_RX; | |
187 | |
188 switch(command) | |
189 { | |
190 case FIFO_NONE: | |
191 break; | |
192 case UPDATEON_ARM9: | |
193 REG_IME = 0; | |
194 MixSound(); | |
195 REG_IME = 1; | |
196 SendCommandToArm7(MIXCOMPLETE_ONARM9); | |
197 break; | |
198 } | |
199 } | |
200 } | |
201 | |
202 | |
203 | |
204 | |
205 | |
206 static int Audio_Available(void) | |
207 { | |
208 return(1); | |
209 } | |
210 | |
211 static void Audio_DeleteDevice(SDL_AudioDevice *device) | |
212 { | |
213 } | |
214 | |
215 static SDL_AudioDevice *Audio_CreateDevice(int devindex) | |
216 { | |
217 | |
218 SDL_AudioDevice *this; | |
219 | |
220 /* Initialize all variables that we clean on shutdown */ | |
221 this = (SDL_AudioDevice *)malloc(sizeof(SDL_AudioDevice)); | |
222 if ( this ) { | |
223 SDL_memset(this, 0, (sizeof *this)); | |
224 this->hidden = (struct SDL_PrivateAudioData *) | |
225 SDL_malloc((sizeof *this->hidden)); | |
226 } | |
227 if ( (this == NULL) || (this->hidden == NULL) ) { | |
228 SDL_OutOfMemory(); | |
229 if ( this ) { | |
230 SDL_free(this); | |
231 } | |
232 return(0); | |
233 } | |
234 SDL_memset(this->hidden, 0, (sizeof *this->hidden)); | |
235 | |
236 /* Set the function pointers */ | |
237 this->OpenAudio = NDS_OpenAudio; | |
238 this->WaitAudio = NDS_WaitAudio; | |
239 this->PlayAudio = NDS_PlayAudio; | |
240 this->GetAudioBuf = NDS_GetAudioBuf; | |
241 this->CloseAudio = NDS_CloseAudio; | |
242 | |
243 this->free = Audio_DeleteDevice; | |
244 //fprintf(stderr,"Audio_CreateDevice\n"); | |
245 return this; | |
246 } | |
247 | |
248 AudioBootStrap NDSAUD_bootstrap = { | |
249 "nds", "NDS audio", | |
250 Audio_Available, Audio_CreateDevice | |
251 }; | |
252 | |
253 | |
254 void static NDS_WaitAudio(_THIS) | |
255 { | |
256 //printf("NDS_WaitAudio\n"); | |
257 } | |
258 | |
259 static void NDS_PlayAudio(_THIS) | |
260 { | |
261 //printf("playing audio\n"); | |
262 if (this->paused) | |
263 return; | |
264 | |
265 } | |
266 | |
267 static Uint8 *NDS_GetAudioBuf(_THIS) | |
268 { | |
269 return NULL;//(this->hidden->mixbuf); | |
270 } | |
271 | |
272 static void NDS_CloseAudio(_THIS) | |
273 { | |
274 /* if ( this->hidden->mixbuf != NULL ) { | |
275 SDL_FreeAudioMem(this->hidden->mixbuf); | |
276 this->hidden->mixbuf = NULL; | |
277 }*/ | |
278 } | |
279 | |
280 static int NDS_OpenAudio(_THIS, SDL_AudioSpec *spec) | |
281 { | |
282 //printf("NDS_OpenAudio\n"); | |
283 int format = 0; | |
284 //switch(spec->format&0xff) { | |
285 //case 8: spec->format = AUDIO_S8;format=8; break; | |
286 //case 16: spec->format = AUDIO_S16LSB;format=16; break; | |
287 //default: | |
288 // SDL_SetError("Unsupported audio format"); | |
289 // return(-1); | |
290 //} | |
291 switch (spec->format&~0x1000) { | |
292 case AUDIO_S8: | |
293 /* Signed 8-bit audio supported */ | |
294 format=8; | |
295 break; | |
296 case AUDIO_U8: | |
297 spec->format ^= 0x80;format=8; | |
298 break; | |
299 case AUDIO_U16: | |
300 /* Unsigned 16-bit audio unsupported, convert to S16 */ | |
301 spec->format ^=0x8000;format=16; | |
302 case AUDIO_S16: | |
303 /* Signed 16-bit audio supported */ | |
304 format=16; | |
305 break; | |
306 } | |
307 /* Update the fragment size as size in bytes */ | |
308 SDL_CalculateAudioSpec(spec); | |
309 | |
310 /* Allocate mixing buffer */ | |
311 //this->hidden->mixlen = spec->size; | |
312 //this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen); | |
313 //if ( this->hidden->mixbuf == NULL ) { | |
314 // SDL_SetError("Out of Memory"); | |
315 // return(-1); | |
316 //} | |
317 | |
318 SDL_NDSAudio_mutex = 0; | |
319 sdl_nds_audiodevice=this; | |
320 | |
321 irqInit(); | |
322 irqSet(IRQ_VBLANK,&InterruptHandler); | |
323 irqSet(IRQ_FIFO_NOT_EMPTY,&FiFoHandler); | |
324 irqEnable(IRQ_FIFO_NOT_EMPTY); | |
325 | |
326 REG_IPC_FIFO_CR = IPC_FIFO_ENABLE | IPC_FIFO_SEND_CLEAR | IPC_FIFO_RECV_IRQ; | |
327 | |
328 | |
329 | |
330 SoundSystemInit(spec->freq,spec->size,0,format); | |
331 SoundStartMixer(); | |
332 | |
333 | |
334 return(1); | |
335 } |