comparison src/audio/mint/SDL_mintaudio_dma8.c @ 644:594422ab8f9f

Atari MiNT: added more audio drivers
author Patrice Mandin <patmandin@gmail.com>
date Mon, 07 Jul 2003 19:16:03 +0000
parents
children c4803992e09c
comparison
equal deleted inserted replaced
643:564716cfb502 644:594422ab8f9f
1 /*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 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 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with this library; if not, write to the Free
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19 Sam Lantinga
20 slouken@libsdl.org
21 */
22
23 /*
24 MiNT audio driver
25 using DMA 8bits (hardware access)
26
27 Patrice Mandin
28 */
29
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <string.h>
33
34 /* Mint includes */
35 #include <mint/osbind.h>
36 #include <mint/falcon.h>
37 #include <mint/cookie.h>
38
39 #include "SDL_endian.h"
40 #include "SDL_audio.h"
41 #include "SDL_audio_c.h"
42 #include "SDL_audiomem.h"
43 #include "SDL_sysaudio.h"
44
45 #include "SDL_atarimxalloc_c.h"
46
47 #include "SDL_mintaudio.h"
48 #include "SDL_mintaudio_dma8.h"
49
50 /*--- Defines ---*/
51
52 #define MINT_AUDIO_DRIVER_NAME "mint_dma8"
53
54 /* Debug print info */
55 #define DEBUG_NAME "audio:dma8: "
56 #if 0
57 #define DEBUG_PRINT(what) \
58 { \
59 printf what; \
60 }
61 #else
62 #define DEBUG_PRINT(what)
63 #endif
64
65 /*--- Static variables ---*/
66
67 static unsigned long cookie_snd, cookie_mch;
68
69 /*--- Audio driver functions ---*/
70
71 static void Mint_CloseAudio(_THIS);
72 static int Mint_OpenAudio(_THIS, SDL_AudioSpec *spec);
73 static void Mint_LockAudio(_THIS);
74 static void Mint_UnlockAudio(_THIS);
75
76 /* To check/init hardware audio */
77 static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec);
78 static void Mint_InitAudio(_THIS, SDL_AudioSpec *spec);
79
80 /*--- Audio driver bootstrap functions ---*/
81
82 static int Audio_Available(void)
83 {
84 const char *envr = getenv("SDL_AUDIODRIVER");
85
86 /* Check if user asked a different audio driver */
87 if ((envr) && (strcmp(envr, MINT_AUDIO_DRIVER_NAME)!=0)) {
88 DEBUG_PRINT((DEBUG_NAME "user asked a different audio driver\n"));
89 return 0;
90 }
91
92 /* Cookie _MCH present ? if not, assume ST machine */
93 if (Getcookie(C__MCH, &cookie_mch) == C_NOTFOUND) {
94 cookie_mch = MCH_ST;
95 }
96
97 /* Cookie _SND present ? if not, assume ST machine */
98 if (Getcookie(C__SND, &cookie_snd) == C_NOTFOUND) {
99 cookie_snd = SND_PSG;
100 }
101
102 /* Check if we have 8 bits audio */
103 if ((cookie_snd & SND_8BIT)==0) {
104 DEBUG_PRINT((DEBUG_NAME "no 8 bits sound\n"));
105 return(0);
106 }
107
108 if ((cookie_mch>>16)>MCH_F30) {
109 DEBUG_PRINT((DEBUG_NAME "unknown 8 bits audio chip\n"));
110 return 0;
111 }
112
113 /* Check if audio is lockable */
114 if ((cookie_mch>>16) == MCH_F30) {
115 if (Locksnd()!=1) {
116 DEBUG_PRINT((DEBUG_NAME "audio locked by other application\n"));
117 return(0);
118 }
119
120 Unlocksnd();
121 }
122
123 DEBUG_PRINT((DEBUG_NAME "8 bits audio available!\n"));
124 return(1);
125 }
126
127 static void Audio_DeleteDevice(SDL_AudioDevice *device)
128 {
129 free(device->hidden);
130 free(device);
131 }
132
133 static SDL_AudioDevice *Audio_CreateDevice(int devindex)
134 {
135 SDL_AudioDevice *this;
136
137 /* Initialize all variables that we clean on shutdown */
138 this = (SDL_AudioDevice *)malloc(sizeof(SDL_AudioDevice));
139 if ( this ) {
140 memset(this, 0, (sizeof *this));
141 this->hidden = (struct SDL_PrivateAudioData *)
142 malloc((sizeof *this->hidden));
143 }
144 if ( (this == NULL) || (this->hidden == NULL) ) {
145 SDL_OutOfMemory();
146 if ( this ) {
147 free(this);
148 }
149 return(0);
150 }
151 memset(this->hidden, 0, (sizeof *this->hidden));
152
153 /* Set the function pointers */
154 this->OpenAudio = Mint_OpenAudio;
155 this->CloseAudio = Mint_CloseAudio;
156 this->LockAudio = Mint_LockAudio;
157 this->UnlockAudio = Mint_UnlockAudio;
158 this->free = Audio_DeleteDevice;
159
160 return this;
161 }
162
163 AudioBootStrap MINTAUDIO_DMA8_bootstrap = {
164 MINT_AUDIO_DRIVER_NAME, "MiNT DMA 8 bits audio driver",
165 Audio_Available, Audio_CreateDevice
166 };
167
168 static void Mint_LockAudio(_THIS)
169 {
170 void *oldpile;
171
172 /* Stop replay */
173 oldpile=(void *)Super(0);
174 DMAAUDIO_IO.control=0;
175 Super(oldpile);
176 }
177
178 static void Mint_UnlockAudio(_THIS)
179 {
180 void *oldpile;
181
182 /* Restart replay */
183 oldpile=(void *)Super(0);
184 DMAAUDIO_IO.control=3;
185 Super(oldpile);
186 }
187
188 static void Mint_CloseAudio(_THIS)
189 {
190 void *oldpile;
191
192 /* Stop replay */
193 oldpile=(void *)Super(0);
194 DMAAUDIO_IO.control=0;
195 Super(oldpile);
196
197 DEBUG_PRINT((DEBUG_NAME "closeaudio: replay stopped\n"));
198
199 /* Disable interrupt */
200 Jdisint(MFP_DMASOUND);
201
202 DEBUG_PRINT((DEBUG_NAME "closeaudio: interrupt disabled\n"));
203
204 /* Wait if currently playing sound */
205 while (SDL_MintAudio_mutex != 0) {
206 }
207
208 DEBUG_PRINT((DEBUG_NAME "closeaudio: no more interrupt running\n"));
209
210 /* Clear buffers */
211 if (SDL_MintAudio_audiobuf[0]) {
212 Mfree(SDL_MintAudio_audiobuf[0]);
213 SDL_MintAudio_audiobuf[0] = SDL_MintAudio_audiobuf[1] = NULL;
214 }
215
216 DEBUG_PRINT((DEBUG_NAME "closeaudio: buffers freed\n"));
217 }
218
219 static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec)
220 {
221 int i, masterprediv;
222 unsigned long masterclock;
223
224 DEBUG_PRINT((DEBUG_NAME "asked: %d bits, ",spec->format & 0x00ff));
225 DEBUG_PRINT(("signed=%d, ", ((spec->format & 0x8000)!=0)));
226 DEBUG_PRINT(("big endian=%d, ", ((spec->format & 0x8000)!=0)));
227 DEBUG_PRINT(("channels=%d, ", spec->channels));
228 DEBUG_PRINT(("freq=%d\n", spec->freq));
229
230 /* Check formats available */
231 spec->format = AUDIO_S8;
232
233 /* Calculate and select the closest frequency */
234 MINTAUDIO_nfreq=4;
235 MINTAUDIO_sfreq=0;
236 masterclock=MASTERCLOCK_STE;
237 masterprediv=MASTERPREDIV_STE;
238 switch(cookie_mch>>16) {
239 /*
240 case MCH_STE:
241 masterclock=MASTERCLOCK_STE;
242 masterprediv=MASTERPREDIV_STE;
243 break;
244 */
245 case MCH_TT:
246 masterclock=MASTERCLOCK_TT;
247 masterprediv=MASTERPREDIV_TT;
248 break;
249 case MCH_F30:
250 masterclock=MASTERCLOCK_FALCON1;
251 masterprediv=MASTERPREDIV_FALCON<<1;
252 MINTAUDIO_nfreq=3;
253 MINTAUDIO_sfreq=1;
254 break;
255 }
256 for (i=MINTAUDIO_sfreq;i<MINTAUDIO_nfreq;i++) {
257 MINTAUDIO_hardfreq[i]=masterclock/(masterprediv*(1<<i));
258 DEBUG_PRINT((DEBUG_NAME "calc:freq(%d)=%lu\n", i, MINTAUDIO_hardfreq[i]));
259 }
260
261 MINTAUDIO_numfreq=SDL_MintAudio_SearchFrequency(this, 0, spec->freq);
262 spec->freq=MINTAUDIO_hardfreq[MINTAUDIO_numfreq];
263
264 DEBUG_PRINT((DEBUG_NAME "obtained: %d bits, ",spec->format & 0x00ff));
265 DEBUG_PRINT(("signed=%d, ", ((spec->format & 0x8000)!=0)));
266 DEBUG_PRINT(("big endian=%d, ", ((spec->format & 0x8000)!=0)));
267 DEBUG_PRINT(("channels=%d, ", spec->channels));
268 DEBUG_PRINT(("freq=%d\n", spec->freq));
269
270 return 0;
271 }
272
273 static void Mint_InitAudio(_THIS, SDL_AudioSpec *spec)
274 {
275 void *oldpile;
276 unsigned long buffer;
277 unsigned char mode;
278
279 /* Set replay tracks */
280 if (cookie_snd & SND_16BIT) {
281 Settracks(0,0);
282 Setmontracks(0);
283 }
284
285 oldpile=(void *)Super(0);
286
287 /* Stop currently playing sound */
288 DMAAUDIO_IO.control=0;
289
290 /* Set buffer */
291 buffer = (unsigned long) SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf];
292 DMAAUDIO_IO.start_high = (buffer>>16) & 255;
293 DMAAUDIO_IO.start_mid = (buffer>>8) & 255;
294 DMAAUDIO_IO.start_low = buffer & 255;
295
296 buffer += SDL_MintAudio_audiosize;
297 DMAAUDIO_IO.end_high = (buffer>>16) & 255;
298 DMAAUDIO_IO.end_mid = (buffer>>8) & 255;
299 DMAAUDIO_IO.end_low = buffer & 255;
300
301 mode = 3-MINTAUDIO_numfreq;
302 if (spec->channels==1) {
303 mode |= 1<<7;
304 }
305 DMAAUDIO_IO.mode = mode;
306
307 /* Set interrupt */
308 Jdisint(MFP_DMASOUND);
309 Xbtimer(XB_TIMERA, 8, 1, SDL_MintAudio_Dma8Interrupt);
310 Jenabint(MFP_DMASOUND);
311
312 /* Go */
313 DMAAUDIO_IO.control = 3; /* playback + repeat */
314
315 Super(oldpile);
316 }
317
318 static int Mint_OpenAudio(_THIS, SDL_AudioSpec *spec)
319 {
320 SDL_MintAudio_device = this;
321
322 /* Check audio capabilities */
323 if (Mint_CheckAudio(this, spec)==-1) {
324 return -1;
325 }
326
327 SDL_CalculateAudioSpec(spec);
328
329 /* Allocate memory for audio buffers in DMA-able RAM */
330 spec->size = spec->samples;
331 spec->size *= spec->channels;
332 spec->size *= (spec->format & 0xFF)/8;
333
334 DEBUG_PRINT((DEBUG_NAME "buffer size=%d\n", spec->size));
335
336 SDL_MintAudio_audiobuf[0] = Atari_SysMalloc(spec->size *2, MX_STRAM);
337 if (SDL_MintAudio_audiobuf[0]==NULL) {
338 SDL_SetError("MINT_OpenAudio: Not enough memory for audio buffer");
339 return (-1);
340 }
341 SDL_MintAudio_audiobuf[1] = SDL_MintAudio_audiobuf[0] + spec->size ;
342 SDL_MintAudio_numbuf=0;
343 memset(SDL_MintAudio_audiobuf[0], spec->silence, spec->size *2);
344 SDL_MintAudio_audiosize = spec->size;
345 SDL_MintAudio_mutex = 0;
346
347 DEBUG_PRINT((DEBUG_NAME "buffer 0 at 0x%08x\n", SDL_MintAudio_audiobuf[0]));
348 DEBUG_PRINT((DEBUG_NAME "buffer 1 at 0x%08x\n", SDL_MintAudio_audiobuf[1]));
349
350 /* Setup audio hardware */
351 Mint_InitAudio(this, spec);
352
353 return(1); /* We don't use threaded audio */
354 }