SDL-1.2.14
[sdl_omap.git] / src / audio / nds / SDL_ndsaudio.c
1 /*
2     SDL - Simple DirectMedia Layer
3     Copyright (C) 1997-2009 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 }