| /* |
| SDL - Simple DirectMedia Layer |
| Copyright (C) 1997-2012 Sam Lantinga |
| |
| This library is free software; you can redistribute it and/or |
| modify it under the terms of the GNU Lesser General Public |
| License as published by the Free Software Foundation; either |
| version 2.1 of the License, or (at your option) any later version. |
| |
| This library is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| Lesser General Public License for more details. |
| |
| You should have received a copy of the GNU Lesser General Public |
| License along with this library; if not, write to the Free Software |
| Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
| |
| Sam Lantinga |
| slouken@libsdl.org |
| */ |
| #include "SDL_config.h" |
| |
| /* Allow access to a raw mixing buffer */ |
| #include <nds.h> |
| #include "SDL.h" |
| #include "SDL_endian.h" |
| #include "SDL_timer.h" |
| #include "SDL_audio.h" |
| #include "../SDL_audiomem.h" |
| #include "../SDL_audio_c.h" |
| #include "SDL_ndsaudio.h" |
| #include "soundcommon.h" |
| |
| |
| /* Audio driver functions */ |
| static int NDS_OpenAudio(_THIS, SDL_AudioSpec *spec); |
| static void NDS_WaitAudio(_THIS); |
| static void NDS_PlayAudio(_THIS); |
| static Uint8 *NDS_GetAudioBuf(_THIS); |
| static void NDS_CloseAudio(_THIS); |
| |
| /* Audio driver bootstrap functions */ |
| |
| u32 framecounter = 0,soundoffset = 0; |
| static SDL_AudioDevice *sdl_nds_audiodevice; |
| |
| //void SoundMixCallback(void *stream,u32 size) |
| //{ |
| // //printf("SoundMixCallback\n"); |
| // |
| // Uint8 *buffer; |
| // |
| // buffer = sdl_nds_audiodevice->hidden->mixbuf; |
| // memset(buffer, sdl_nds_audiodevice->spec.silence, size); |
| // |
| // if (!sdl_nds_audiodevice->paused){ |
| // |
| // |
| // //if (sdl_nds_audiodevice->convert.needed) { |
| // // int silence; |
| // |
| // // if (sdl_nds_audiodevice->convert.src_format == AUDIO_U8 ) { |
| // // silence = 0x80; |
| // // } else { |
| // // silence = 0; |
| // // } |
| // // memset(sdl_nds_audiodevice->convert.buf, silence, sdl_nds_audiodevice->convert.len); |
| // // sdl_nds_audiodevice->spec.callback(sdl_nds_audiodevice->spec.userdata, |
| // // (Uint8 *)sdl_nds_audiodevice->convert.buf,sdl_nds_audiodevice->convert.len); |
| // // SDL_ConvertAudio(&sdl_nds_audiodevice->convert); |
| // // memcpy(buffer, sdl_nds_audiodevice->convert.buf, sdl_nds_audiodevice->convert.len_cvt); |
| // //} else |
| // { |
| // sdl_nds_audiodevice->spec.callback(sdl_nds_audiodevice->spec.userdata, buffer, size); |
| // //memcpy((Sint16 *)stream,buffer, size); |
| // } |
| // |
| // } |
| // |
| // if(soundsystem->format == 8) |
| // { |
| // int i; |
| // s32 *buffer32 = (s32 *)buffer; |
| // s32 *stream32 = (s32 *)stream; |
| // for(i=0;i<size/4;i++){ *stream32++ = buffer32[i] ^ 0x80808080;} |
| // //for(i = 0; i < size; i++) |
| // // ((s8*)stream)[i]=(buffer[i]^0x80); |
| // } |
| // else |
| // { |
| // int i; |
| // for(i = 0; i < size; i++){ |
| // //((short*)stream)[i] =(short)buffer[i] << 8; // sound 8bit ---> buffer 16bit |
| // //if (buffer[i] &0x80) |
| // //((Sint16*)stream)[i] = 0xff00 | buffer[i]; |
| // ((Sint16*)stream)[i] = (buffer[i] - 128) << 8; |
| // |
| // //else |
| // // ((Sint16*)stream)[i] = buffer[i]; |
| // } |
| // //register signed char *pSrc =buffer; |
| // //register short *pDest =stream; |
| // //int x; |
| // // for (x=size; x>0; x--) |
| // // { |
| // // register short temp = (((short)*pSrc)-128)<<8; |
| // // pSrc++; |
| // // *pDest++ = temp; |
| // // } |
| // |
| // //memcpy((Sint16 *)stream,buffer, size); |
| // } |
| //} |
| |
| void SoundMixCallback(void *stream,u32 len) |
| { |
| SDL_AudioDevice *audio = (SDL_AudioDevice *)sdl_nds_audiodevice; |
| |
| /* Silence the buffer, since it's ours */ |
| SDL_memset(stream, audio->spec.silence, len); |
| |
| /* Only do soemthing if audio is enabled */ |
| if ( ! audio->enabled ) |
| return; |
| |
| if ( ! audio->paused ) { |
| if ( audio->convert.needed ) { |
| //fprintf(stderr,"converting audio\n"); |
| SDL_mutexP(audio->mixer_lock); |
| (*audio->spec.callback)(audio->spec.userdata, |
| (Uint8 *)audio->convert.buf,audio->convert.len); |
| SDL_mutexV(audio->mixer_lock); |
| SDL_ConvertAudio(&audio->convert); |
| SDL_memcpy(stream,audio->convert.buf,audio->convert.len_cvt); |
| } else { |
| SDL_mutexP(audio->mixer_lock); |
| (*audio->spec.callback)(audio->spec.userdata, |
| (Uint8 *)stream, len); |
| SDL_mutexV(audio->mixer_lock); |
| } |
| } |
| return; |
| } |
| void MixSound(void) |
| { |
| int remain; |
| |
| if(soundsystem->format == 8) |
| { |
| if((soundsystem->soundcursor + soundsystem->numsamples) > soundsystem->buffersize) |
| { |
| SoundMixCallback(&soundsystem->mixbuffer[soundsystem->soundcursor],soundsystem->buffersize - soundsystem->soundcursor); |
| remain = soundsystem->numsamples - (soundsystem->buffersize - soundsystem->soundcursor); |
| SoundMixCallback(soundsystem->mixbuffer,remain); |
| } |
| else |
| { |
| SoundMixCallback(&soundsystem->mixbuffer[soundsystem->soundcursor],soundsystem->numsamples); |
| } |
| } |
| else |
| { |
| if((soundsystem->soundcursor + soundsystem->numsamples) > (soundsystem->buffersize >> 1)) |
| { |
| SoundMixCallback(&soundsystem->mixbuffer[soundsystem->soundcursor << 1],(soundsystem->buffersize >> 1) - soundsystem->soundcursor); |
| remain = soundsystem->numsamples - ((soundsystem->buffersize >> 1) - soundsystem->soundcursor); |
| SoundMixCallback(soundsystem->mixbuffer,remain); |
| } |
| else |
| { |
| SoundMixCallback(&soundsystem->mixbuffer[soundsystem->soundcursor << 1],soundsystem->numsamples); |
| } |
| } |
| } |
| |
| void InterruptHandler(void) |
| { |
| framecounter++; |
| } |
| void FiFoHandler(void) |
| { |
| u32 command; |
| while ( !(REG_IPC_FIFO_CR & (IPC_FIFO_RECV_EMPTY)) ) |
| { |
| command = REG_IPC_FIFO_RX; |
| |
| switch(command) |
| { |
| case FIFO_NONE: |
| break; |
| case UPDATEON_ARM9: |
| REG_IME = 0; |
| MixSound(); |
| REG_IME = 1; |
| SendCommandToArm7(MIXCOMPLETE_ONARM9); |
| break; |
| } |
| } |
| } |
| |
| |
| |
| |
| |
| static int Audio_Available(void) |
| { |
| return(1); |
| } |
| |
| static void Audio_DeleteDevice(SDL_AudioDevice *device) |
| { |
| } |
| |
| static SDL_AudioDevice *Audio_CreateDevice(int devindex) |
| { |
| |
| SDL_AudioDevice *this; |
| |
| /* Initialize all variables that we clean on shutdown */ |
| this = (SDL_AudioDevice *)malloc(sizeof(SDL_AudioDevice)); |
| if ( this ) { |
| SDL_memset(this, 0, (sizeof *this)); |
| this->hidden = (struct SDL_PrivateAudioData *) |
| SDL_malloc((sizeof *this->hidden)); |
| } |
| if ( (this == NULL) || (this->hidden == NULL) ) { |
| SDL_OutOfMemory(); |
| if ( this ) { |
| SDL_free(this); |
| } |
| return(0); |
| } |
| SDL_memset(this->hidden, 0, (sizeof *this->hidden)); |
| |
| /* Set the function pointers */ |
| this->OpenAudio = NDS_OpenAudio; |
| this->WaitAudio = NDS_WaitAudio; |
| this->PlayAudio = NDS_PlayAudio; |
| this->GetAudioBuf = NDS_GetAudioBuf; |
| this->CloseAudio = NDS_CloseAudio; |
| |
| this->free = Audio_DeleteDevice; |
| //fprintf(stderr,"Audio_CreateDevice\n"); |
| return this; |
| } |
| |
| AudioBootStrap NDSAUD_bootstrap = { |
| "nds", "NDS audio", |
| Audio_Available, Audio_CreateDevice |
| }; |
| |
| |
| void static NDS_WaitAudio(_THIS) |
| { |
| //printf("NDS_WaitAudio\n"); |
| } |
| |
| static void NDS_PlayAudio(_THIS) |
| { |
| //printf("playing audio\n"); |
| if (this->paused) |
| return; |
| |
| } |
| |
| static Uint8 *NDS_GetAudioBuf(_THIS) |
| { |
| return NULL;//(this->hidden->mixbuf); |
| } |
| |
| static void NDS_CloseAudio(_THIS) |
| { |
| /* if ( this->hidden->mixbuf != NULL ) { |
| SDL_FreeAudioMem(this->hidden->mixbuf); |
| this->hidden->mixbuf = NULL; |
| }*/ |
| } |
| |
| static int NDS_OpenAudio(_THIS, SDL_AudioSpec *spec) |
| { |
| //printf("NDS_OpenAudio\n"); |
| int format = 0; |
| //switch(spec->format&0xff) { |
| //case 8: spec->format = AUDIO_S8;format=8; break; |
| //case 16: spec->format = AUDIO_S16LSB;format=16; break; |
| //default: |
| // SDL_SetError("Unsupported audio format"); |
| // return(-1); |
| //} |
| switch (spec->format&~0x1000) { |
| case AUDIO_S8: |
| /* Signed 8-bit audio supported */ |
| format=8; |
| break; |
| case AUDIO_U8: |
| spec->format ^= 0x80;format=8; |
| break; |
| case AUDIO_U16: |
| /* Unsigned 16-bit audio unsupported, convert to S16 */ |
| spec->format ^=0x8000;format=16; |
| case AUDIO_S16: |
| /* Signed 16-bit audio supported */ |
| format=16; |
| break; |
| } |
| /* Update the fragment size as size in bytes */ |
| SDL_CalculateAudioSpec(spec); |
| |
| /* Allocate mixing buffer */ |
| //this->hidden->mixlen = spec->size; |
| //this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen); |
| //if ( this->hidden->mixbuf == NULL ) { |
| // SDL_SetError("Out of Memory"); |
| // return(-1); |
| //} |
| |
| SDL_NDSAudio_mutex = 0; |
| sdl_nds_audiodevice=this; |
| |
| irqInit(); |
| irqSet(IRQ_VBLANK,&InterruptHandler); |
| irqSet(IRQ_FIFO_NOT_EMPTY,&FiFoHandler); |
| irqEnable(IRQ_FIFO_NOT_EMPTY); |
| |
| REG_IPC_FIFO_CR = IPC_FIFO_ENABLE | IPC_FIFO_SEND_CLEAR | IPC_FIFO_RECV_IRQ; |
| |
| |
| |
| SoundSystemInit(spec->freq,spec->size,0,format); |
| SoundStartMixer(); |
| |
| |
| return(1); |
| } |