1 /* 2 SDL - Simple DirectMedia Layer 3 Copyright (C) 1997-2012 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 (at) 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 } 336