Home | History | Annotate | Download | only in nds
      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