2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2009 Sam Lantinga
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.
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.
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
22 #include "SDL_config.h"
24 /* Allow access to a raw mixing buffer */
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"
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);
43 /* Audio driver bootstrap functions */
45 u32 framecounter = 0,soundoffset = 0;
46 static SDL_AudioDevice *sdl_nds_audiodevice;
48 //void SoundMixCallback(void *stream,u32 size)
50 // //printf("SoundMixCallback\n");
54 // buffer = sdl_nds_audiodevice->hidden->mixbuf;
55 // memset(buffer, sdl_nds_audiodevice->spec.silence, size);
57 // if (!sdl_nds_audiodevice->paused){
60 // //if (sdl_nds_audiodevice->convert.needed) {
63 // // if (sdl_nds_audiodevice->convert.src_format == AUDIO_U8 ) {
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);
75 // sdl_nds_audiodevice->spec.callback(sdl_nds_audiodevice->spec.userdata, buffer, size);
76 // //memcpy((Sint16 *)stream,buffer, size);
81 // if(soundsystem->format == 8)
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);
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;
100 // // ((Sint16*)stream)[i] = buffer[i];
102 // //register signed char *pSrc =buffer;
103 // //register short *pDest =stream;
105 // // for (x=size; x>0; x--)
107 // // register short temp = (((short)*pSrc)-128)<<8;
109 // // *pDest++ = temp;
112 // //memcpy((Sint16 *)stream,buffer, size);
116 void SoundMixCallback(void *stream,u32 len)
118 SDL_AudioDevice *audio = (SDL_AudioDevice *)sdl_nds_audiodevice;
120 /* Silence the buffer, since it's ours */
121 SDL_memset(stream, audio->spec.silence, len);
123 /* Only do soemthing if audio is enabled */
124 if ( ! audio->enabled )
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);
137 SDL_mutexP(audio->mixer_lock);
138 (*audio->spec.callback)(audio->spec.userdata,
139 (Uint8 *)stream, len);
140 SDL_mutexV(audio->mixer_lock);
149 if(soundsystem->format == 8)
151 if((soundsystem->soundcursor + soundsystem->numsamples) > soundsystem->buffersize)
153 SoundMixCallback(&soundsystem->mixbuffer[soundsystem->soundcursor],soundsystem->buffersize - soundsystem->soundcursor);
154 remain = soundsystem->numsamples - (soundsystem->buffersize - soundsystem->soundcursor);
155 SoundMixCallback(soundsystem->mixbuffer,remain);
159 SoundMixCallback(&soundsystem->mixbuffer[soundsystem->soundcursor],soundsystem->numsamples);
164 if((soundsystem->soundcursor + soundsystem->numsamples) > (soundsystem->buffersize >> 1))
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);
172 SoundMixCallback(&soundsystem->mixbuffer[soundsystem->soundcursor << 1],soundsystem->numsamples);
177 void InterruptHandler(void)
181 void FiFoHandler(void)
184 while ( !(REG_IPC_FIFO_CR & (IPC_FIFO_RECV_EMPTY)) )
186 command = REG_IPC_FIFO_RX;
196 SendCommandToArm7(MIXCOMPLETE_ONARM9);
206 static int Audio_Available(void)
211 static void Audio_DeleteDevice(SDL_AudioDevice *device)
215 static SDL_AudioDevice *Audio_CreateDevice(int devindex)
218 SDL_AudioDevice *this;
220 /* Initialize all variables that we clean on shutdown */
221 this = (SDL_AudioDevice *)malloc(sizeof(SDL_AudioDevice));
223 SDL_memset(this, 0, (sizeof *this));
224 this->hidden = (struct SDL_PrivateAudioData *)
225 SDL_malloc((sizeof *this->hidden));
227 if ( (this == NULL) || (this->hidden == NULL) ) {
234 SDL_memset(this->hidden, 0, (sizeof *this->hidden));
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;
243 this->free = Audio_DeleteDevice;
244 //fprintf(stderr,"Audio_CreateDevice\n");
248 AudioBootStrap NDSAUD_bootstrap = {
250 Audio_Available, Audio_CreateDevice
254 void static NDS_WaitAudio(_THIS)
256 //printf("NDS_WaitAudio\n");
259 static void NDS_PlayAudio(_THIS)
261 //printf("playing audio\n");
267 static Uint8 *NDS_GetAudioBuf(_THIS)
269 return NULL;//(this->hidden->mixbuf);
272 static void NDS_CloseAudio(_THIS)
274 /* if ( this->hidden->mixbuf != NULL ) {
275 SDL_FreeAudioMem(this->hidden->mixbuf);
276 this->hidden->mixbuf = NULL;
280 static int NDS_OpenAudio(_THIS, SDL_AudioSpec *spec)
282 //printf("NDS_OpenAudio\n");
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;
288 // SDL_SetError("Unsupported audio format");
291 switch (spec->format&~0x1000) {
293 /* Signed 8-bit audio supported */
297 spec->format ^= 0x80;format=8;
300 /* Unsigned 16-bit audio unsupported, convert to S16 */
301 spec->format ^=0x8000;format=16;
303 /* Signed 16-bit audio supported */
307 /* Update the fragment size as size in bytes */
308 SDL_CalculateAudioSpec(spec);
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");
318 SDL_NDSAudio_mutex = 0;
319 sdl_nds_audiodevice=this;
322 irqSet(IRQ_VBLANK,&InterruptHandler);
323 irqSet(IRQ_FIFO_NOT_EMPTY,&FiFoHandler);
324 irqEnable(IRQ_FIFO_NOT_EMPTY);
326 REG_IPC_FIFO_CR = IPC_FIFO_ENABLE | IPC_FIFO_SEND_CLEAR | IPC_FIFO_RECV_IRQ;
330 SoundSystemInit(spec->freq,spec->size,0,format);