comparison src/audio/dc/SDL_dcaudio.c @ 1662:782fd950bd46 SDL-1.3

Revamp of the video system in progress - adding support for multiple displays, multiple windows, and a full video mode selection API. WARNING: None of the video drivers have been updated for the new API yet! The API is still under design and very fluid. The code is now run through a consistent indent format: indent -i4 -nut -nsc -br -ce The headers are being converted to automatically generate doxygen documentation.
author Sam Lantinga <slouken@libsdl.org>
date Sun, 28 May 2006 13:04:16 +0000
parents 11134dc42da8
children 4da1ee79c9af
comparison
equal deleted inserted replaced
1661:281d3f4870e5 1662:782fd950bd46
33 33
34 #include "aica.h" 34 #include "aica.h"
35 #include <dc/spu.h> 35 #include <dc/spu.h>
36 36
37 /* Audio driver functions */ 37 /* Audio driver functions */
38 static int DCAUD_OpenAudio(_THIS, SDL_AudioSpec *spec); 38 static int DCAUD_OpenAudio (_THIS, SDL_AudioSpec * spec);
39 static void DCAUD_WaitAudio(_THIS); 39 static void DCAUD_WaitAudio (_THIS);
40 static void DCAUD_PlayAudio(_THIS); 40 static void DCAUD_PlayAudio (_THIS);
41 static Uint8 *DCAUD_GetAudioBuf(_THIS); 41 static Uint8 *DCAUD_GetAudioBuf (_THIS);
42 static void DCAUD_CloseAudio(_THIS); 42 static void DCAUD_CloseAudio (_THIS);
43 43
44 /* Audio driver bootstrap functions */ 44 /* Audio driver bootstrap functions */
45 static int DCAUD_Available(void) 45 static int
46 { 46 DCAUD_Available (void)
47 return 1; 47 {
48 } 48 return 1;
49 49 }
50 static void DCAUD_DeleteDevice(SDL_AudioDevice *device) 50
51 { 51 static void
52 SDL_free(device->hidden); 52 DCAUD_DeleteDevice (SDL_AudioDevice * device)
53 SDL_free(device); 53 {
54 } 54 SDL_free (device->hidden);
55 55 SDL_free (device);
56 static SDL_AudioDevice *DCAUD_CreateDevice(int devindex) 56 }
57 { 57
58 SDL_AudioDevice *this; 58 static SDL_AudioDevice *
59 59 DCAUD_CreateDevice (int devindex)
60 /* Initialize all variables that we clean on shutdown */ 60 {
61 this = (SDL_AudioDevice *)SDL_malloc(sizeof(SDL_AudioDevice)); 61 SDL_AudioDevice *this;
62 if ( this ) { 62
63 SDL_memset(this, 0, (sizeof *this)); 63 /* Initialize all variables that we clean on shutdown */
64 this->hidden = (struct SDL_PrivateAudioData *) 64 this = (SDL_AudioDevice *) SDL_malloc (sizeof (SDL_AudioDevice));
65 SDL_malloc((sizeof *this->hidden)); 65 if (this) {
66 } 66 SDL_memset (this, 0, (sizeof *this));
67 if ( (this == NULL) || (this->hidden == NULL) ) { 67 this->hidden = (struct SDL_PrivateAudioData *)
68 SDL_OutOfMemory(); 68 SDL_malloc ((sizeof *this->hidden));
69 if ( this ) { 69 }
70 SDL_free(this); 70 if ((this == NULL) || (this->hidden == NULL)) {
71 } 71 SDL_OutOfMemory ();
72 return(0); 72 if (this) {
73 } 73 SDL_free (this);
74 SDL_memset(this->hidden, 0, (sizeof *this->hidden)); 74 }
75 75 return (0);
76 /* Set the function pointers */ 76 }
77 this->OpenAudio = DCAUD_OpenAudio; 77 SDL_memset (this->hidden, 0, (sizeof *this->hidden));
78 this->WaitAudio = DCAUD_WaitAudio; 78
79 this->PlayAudio = DCAUD_PlayAudio; 79 /* Set the function pointers */
80 this->GetAudioBuf = DCAUD_GetAudioBuf; 80 this->OpenAudio = DCAUD_OpenAudio;
81 this->CloseAudio = DCAUD_CloseAudio; 81 this->WaitAudio = DCAUD_WaitAudio;
82 82 this->PlayAudio = DCAUD_PlayAudio;
83 this->free = DCAUD_DeleteDevice; 83 this->GetAudioBuf = DCAUD_GetAudioBuf;
84 84 this->CloseAudio = DCAUD_CloseAudio;
85 spu_init(); 85
86 86 this->free = DCAUD_DeleteDevice;
87 return this; 87
88 spu_init ();
89
90 return this;
88 } 91 }
89 92
90 AudioBootStrap DCAUD_bootstrap = { 93 AudioBootStrap DCAUD_bootstrap = {
91 "dcaudio", "Dreamcast AICA audio", 94 "dcaudio", "Dreamcast AICA audio",
92 DCAUD_Available, DCAUD_CreateDevice 95 DCAUD_Available, DCAUD_CreateDevice
93 }; 96 };
94 97
95 /* This function waits until it is possible to write a full sound buffer */ 98 /* This function waits until it is possible to write a full sound buffer */
96 static void DCAUD_WaitAudio(_THIS) 99 static void
97 { 100 DCAUD_WaitAudio (_THIS)
98 if (this->hidden->playing) { 101 {
99 /* wait */ 102 if (this->hidden->playing) {
100 while(aica_get_pos(0)/this->spec.samples == this->hidden->nextbuf) { 103 /* wait */
101 thd_pass(); 104 while (aica_get_pos (0) / this->spec.samples == this->hidden->nextbuf) {
102 } 105 thd_pass ();
103 } 106 }
107 }
104 } 108 }
105 109
106 #define SPU_RAM_BASE 0xa0800000 110 #define SPU_RAM_BASE 0xa0800000
107 111
108 static void spu_memload_stereo8(int leftpos,int rightpos,void *src0,size_t size) 112 static void
109 { 113 spu_memload_stereo8 (int leftpos, int rightpos, void *src0, size_t size)
110 uint8 *src = src0; 114 {
111 uint32 *left = (uint32*)(leftpos +SPU_RAM_BASE); 115 uint8 *src = src0;
112 uint32 *right = (uint32*)(rightpos+SPU_RAM_BASE); 116 uint32 *left = (uint32 *) (leftpos + SPU_RAM_BASE);
113 size = (size+7)/8; 117 uint32 *right = (uint32 *) (rightpos + SPU_RAM_BASE);
114 while(size--) { 118 size = (size + 7) / 8;
115 unsigned lval,rval; 119 while (size--) {
116 lval = *src++; 120 unsigned lval, rval;
117 rval = *src++; 121 lval = *src++;
118 lval|= (*src++)<<8; 122 rval = *src++;
119 rval|= (*src++)<<8; 123 lval |= (*src++) << 8;
120 lval|= (*src++)<<16; 124 rval |= (*src++) << 8;
121 rval|= (*src++)<<16; 125 lval |= (*src++) << 16;
122 lval|= (*src++)<<24; 126 rval |= (*src++) << 16;
123 rval|= (*src++)<<24; 127 lval |= (*src++) << 24;
124 g2_write_32(left++,lval); 128 rval |= (*src++) << 24;
125 g2_write_32(right++,rval); 129 g2_write_32 (left++, lval);
126 g2_fifo_wait(); 130 g2_write_32 (right++, rval);
127 } 131 g2_fifo_wait ();
128 } 132 }
129 133 }
130 static void spu_memload_stereo16(int leftpos,int rightpos,void *src0,size_t size) 134
131 { 135 static void
132 uint16 *src = src0; 136 spu_memload_stereo16 (int leftpos, int rightpos, void *src0, size_t size)
133 uint32 *left = (uint32*)(leftpos +SPU_RAM_BASE); 137 {
134 uint32 *right = (uint32*)(rightpos+SPU_RAM_BASE); 138 uint16 *src = src0;
135 size = (size+7)/8; 139 uint32 *left = (uint32 *) (leftpos + SPU_RAM_BASE);
136 while(size--) { 140 uint32 *right = (uint32 *) (rightpos + SPU_RAM_BASE);
137 unsigned lval,rval; 141 size = (size + 7) / 8;
138 lval = *src++; 142 while (size--) {
139 rval = *src++; 143 unsigned lval, rval;
140 lval|= (*src++)<<16; 144 lval = *src++;
141 rval|= (*src++)<<16; 145 rval = *src++;
142 g2_write_32(left++,lval); 146 lval |= (*src++) << 16;
143 g2_write_32(right++,rval); 147 rval |= (*src++) << 16;
144 g2_fifo_wait(); 148 g2_write_32 (left++, lval);
145 } 149 g2_write_32 (right++, rval);
146 } 150 g2_fifo_wait ();
147 151 }
148 static void DCAUD_PlayAudio(_THIS) 152 }
149 { 153
150 SDL_AudioSpec *spec = &this->spec; 154 static void
151 unsigned int offset; 155 DCAUD_PlayAudio (_THIS)
152 156 {
153 if (this->hidden->playing) { 157 SDL_AudioSpec *spec = &this->spec;
154 /* wait */ 158 unsigned int offset;
155 while(aica_get_pos(0)/spec->samples == this->hidden->nextbuf) { 159
156 thd_pass(); 160 if (this->hidden->playing) {
157 } 161 /* wait */
158 } 162 while (aica_get_pos (0) / spec->samples == this->hidden->nextbuf) {
159 163 thd_pass ();
160 offset = this->hidden->nextbuf*spec->size; 164 }
161 this->hidden->nextbuf^=1; 165 }
162 /* Write the audio data, checking for EAGAIN on broken audio drivers */ 166
163 if (spec->channels==1) { 167 offset = this->hidden->nextbuf * spec->size;
164 spu_memload(this->hidden->leftpos+offset,this->hidden->mixbuf,this->hidden->mixlen); 168 this->hidden->nextbuf ^= 1;
165 } else { 169 /* Write the audio data, checking for EAGAIN on broken audio drivers */
166 offset/=2; 170 if (spec->channels == 1) {
167 if ((this->spec.format&255)==8) { 171 spu_memload (this->hidden->leftpos + offset, this->hidden->mixbuf,
168 spu_memload_stereo8(this->hidden->leftpos+offset,this->hidden->rightpos+offset,this->hidden->mixbuf,this->hidden->mixlen); 172 this->hidden->mixlen);
169 } else { 173 } else {
170 spu_memload_stereo16(this->hidden->leftpos+offset,this->hidden->rightpos+offset,this->hidden->mixbuf,this->hidden->mixlen); 174 offset /= 2;
171 } 175 if ((this->spec.format & 255) == 8) {
172 } 176 spu_memload_stereo8 (this->hidden->leftpos + offset,
173 177 this->hidden->rightpos + offset,
174 if (!this->hidden->playing) { 178 this->hidden->mixbuf, this->hidden->mixlen);
175 int mode; 179 } else {
176 this->hidden->playing = 1; 180 spu_memload_stereo16 (this->hidden->leftpos + offset,
177 mode = (spec->format==AUDIO_S8)?SM_8BIT:SM_16BIT; 181 this->hidden->rightpos + offset,
178 if (spec->channels==1) { 182 this->hidden->mixbuf, this->hidden->mixlen);
179 aica_play(0,mode,this->hidden->leftpos,0,spec->samples*2,spec->freq,255,128,1); 183 }
180 } else { 184 }
181 aica_play(0,mode,this->hidden->leftpos ,0,spec->samples*2,spec->freq,255,0,1); 185
182 aica_play(1,mode,this->hidden->rightpos,0,spec->samples*2,spec->freq,255,255,1); 186 if (!this->hidden->playing) {
183 } 187 int mode;
184 } 188 this->hidden->playing = 1;
185 } 189 mode = (spec->format == AUDIO_S8) ? SM_8BIT : SM_16BIT;
186 190 if (spec->channels == 1) {
187 static Uint8 *DCAUD_GetAudioBuf(_THIS) 191 aica_play (0, mode, this->hidden->leftpos, 0,
188 { 192 spec->samples * 2, spec->freq, 255, 128, 1);
189 return(this->hidden->mixbuf); 193 } else {
190 } 194 aica_play (0, mode, this->hidden->leftpos, 0,
191 195 spec->samples * 2, spec->freq, 255, 0, 1);
192 static void DCAUD_CloseAudio(_THIS) 196 aica_play (1, mode, this->hidden->rightpos, 0,
193 { 197 spec->samples * 2, spec->freq, 255, 255, 1);
194 aica_stop(0); 198 }
195 if (this->spec.channels==2) aica_stop(1); 199 }
196 if ( this->hidden->mixbuf != NULL ) { 200 }
197 SDL_FreeAudioMem(this->hidden->mixbuf); 201
198 this->hidden->mixbuf = NULL; 202 static Uint8 *
199 } 203 DCAUD_GetAudioBuf (_THIS)
200 } 204 {
201 205 return (this->hidden->mixbuf);
202 static int DCAUD_OpenAudio(_THIS, SDL_AudioSpec *spec) 206 }
203 { 207
204 switch(spec->format&0xff) { 208 static void
205 case 8: spec->format = AUDIO_S8; break; 209 DCAUD_CloseAudio (_THIS)
206 case 16: spec->format = AUDIO_S16LSB; break; 210 {
207 default: 211 aica_stop (0);
208 SDL_SetError("Unsupported audio format"); 212 if (this->spec.channels == 2)
209 return(-1); 213 aica_stop (1);
210 } 214 if (this->hidden->mixbuf != NULL) {
211 215 SDL_FreeAudioMem (this->hidden->mixbuf);
212 /* Update the fragment size as size in bytes */ 216 this->hidden->mixbuf = NULL;
213 SDL_CalculateAudioSpec(spec); 217 }
214 218 }
215 /* Allocate mixing buffer */ 219
216 this->hidden->mixlen = spec->size; 220 static int
217 this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen); 221 DCAUD_OpenAudio (_THIS, SDL_AudioSpec * spec)
218 if ( this->hidden->mixbuf == NULL ) { 222 {
219 return(-1); 223 switch (spec->format & 0xff) {
220 } 224 case 8:
221 SDL_memset(this->hidden->mixbuf, spec->silence, spec->size); 225 spec->format = AUDIO_S8;
222 this->hidden->leftpos = 0x11000; 226 break;
223 this->hidden->rightpos = 0x11000+spec->size; 227 case 16:
224 this->hidden->playing = 0; 228 spec->format = AUDIO_S16LSB;
225 this->hidden->nextbuf = 0; 229 break;
226 230 default:
227 /* We're ready to rock and roll. :-) */ 231 SDL_SetError ("Unsupported audio format");
228 return(0); 232 return (-1);
229 } 233 }
234
235 /* Update the fragment size as size in bytes */
236 SDL_CalculateAudioSpec (spec);
237
238 /* Allocate mixing buffer */
239 this->hidden->mixlen = spec->size;
240 this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem (this->hidden->mixlen);
241 if (this->hidden->mixbuf == NULL) {
242 return (-1);
243 }
244 SDL_memset (this->hidden->mixbuf, spec->silence, spec->size);
245 this->hidden->leftpos = 0x11000;
246 this->hidden->rightpos = 0x11000 + spec->size;
247 this->hidden->playing = 0;
248 this->hidden->nextbuf = 0;
249
250 /* We're ready to rock and roll. :-) */
251 return (0);
252 }
253
254 /* vi: set ts=4 sw=4 expandtab: */