comparison src/audio/mint/SDL_mintaudio_xbios.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 XBIOS functions (Falcon)
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
49 /*--- Defines ---*/
50
51 #define MINT_AUDIO_DRIVER_NAME "mint_xbios"
52
53 /* Debug print info */
54 #define DEBUG_NAME "audio:xbios: "
55 #if 0
56 #define DEBUG_PRINT(what) \
57 { \
58 printf what; \
59 }
60 #else
61 #define DEBUG_PRINT(what)
62 #endif
63
64 /*--- Static variables ---*/
65
66 static unsigned long cookie_snd;
67
68 /*--- Audio driver functions ---*/
69
70 static void Mint_CloseAudio(_THIS);
71 static int Mint_OpenAudio(_THIS, SDL_AudioSpec *spec);
72 static void Mint_LockAudio(_THIS);
73 static void Mint_UnlockAudio(_THIS);
74
75 /* To check/init hardware audio */
76 static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec);
77 static void Mint_InitAudio(_THIS, SDL_AudioSpec *spec);
78
79 /*--- Audio driver bootstrap functions ---*/
80
81 static int Audio_Available(void)
82 {
83 const char *envr = getenv("SDL_AUDIODRIVER");
84
85 /* Check if user asked a different audio driver */
86 if ((envr) && (strcmp(envr, MINT_AUDIO_DRIVER_NAME)!=0)) {
87 DEBUG_PRINT((DEBUG_NAME "user asked a different audio driver\n"));
88 return(0);
89 }
90
91 /* Cookie _SND present ? if not, assume ST machine */
92 if (Getcookie(C__SND, &cookie_snd) == C_NOTFOUND) {
93 cookie_snd = SND_PSG;
94 }
95
96 /* Check if we have 16 bits audio */
97 if ((cookie_snd & SND_16BIT)==0) {
98 DEBUG_PRINT((DEBUG_NAME "no 16 bits sound\n"));
99 return(0);
100 }
101
102 /* Check if audio is lockable */
103 if (Locksnd()!=1) {
104 DEBUG_PRINT((DEBUG_NAME "audio locked by other application\n"));
105 return(0);
106 }
107
108 Unlocksnd();
109
110 DEBUG_PRINT((DEBUG_NAME "XBIOS audio available!\n"));
111 return(1);
112 }
113
114 static void Audio_DeleteDevice(SDL_AudioDevice *device)
115 {
116 free(device->hidden);
117 free(device);
118 }
119
120 static SDL_AudioDevice *Audio_CreateDevice(int devindex)
121 {
122 SDL_AudioDevice *this;
123
124 /* Initialize all variables that we clean on shutdown */
125 this = (SDL_AudioDevice *)malloc(sizeof(SDL_AudioDevice));
126 if ( this ) {
127 memset(this, 0, (sizeof *this));
128 this->hidden = (struct SDL_PrivateAudioData *)
129 malloc((sizeof *this->hidden));
130 }
131 if ( (this == NULL) || (this->hidden == NULL) ) {
132 SDL_OutOfMemory();
133 if ( this ) {
134 free(this);
135 }
136 return(0);
137 }
138 memset(this->hidden, 0, (sizeof *this->hidden));
139
140 /* Set the function pointers */
141 this->OpenAudio = Mint_OpenAudio;
142 this->CloseAudio = Mint_CloseAudio;
143 this->LockAudio = Mint_LockAudio;
144 this->UnlockAudio = Mint_UnlockAudio;
145 this->free = Audio_DeleteDevice;
146
147 return this;
148 }
149
150 AudioBootStrap MINTAUDIO_XBIOS_bootstrap = {
151 MINT_AUDIO_DRIVER_NAME, "MiNT XBIOS audio driver",
152 Audio_Available, Audio_CreateDevice
153 };
154
155 static void Mint_LockAudio(_THIS)
156 {
157 /* Stop replay */
158 Buffoper(0);
159 }
160
161 static void Mint_UnlockAudio(_THIS)
162 {
163 /* Restart replay */
164 Buffoper(SB_PLA_ENA|SB_PLA_RPT);
165 }
166
167 static void Mint_CloseAudio(_THIS)
168 {
169 /* Stop replay */
170 Buffoper(0);
171
172 /* Uninstall interrupt */
173 Jdisint(MFP_DMASOUND);
174
175 /* Wait if currently playing sound */
176 while (SDL_MintAudio_mutex != 0) {
177 }
178
179 /* Clear buffers */
180 if (SDL_MintAudio_audiobuf[0]) {
181 Mfree(SDL_MintAudio_audiobuf[0]);
182 SDL_MintAudio_audiobuf[0] = SDL_MintAudio_audiobuf[1] = NULL;
183 }
184
185 /* Unlock sound system */
186 Unlocksnd();
187 }
188
189 static int Mint_CheckAudio(_THIS, SDL_AudioSpec *spec)
190 {
191 int i;
192
193 DEBUG_PRINT((DEBUG_NAME "asked: %d bits, ",spec->format & 0x00ff));
194 DEBUG_PRINT(("signed=%d, ", ((spec->format & 0x8000)!=0)));
195 DEBUG_PRINT(("big endian=%d, ", ((spec->format & 0x8000)!=0)));
196 DEBUG_PRINT(("channels=%d, ", spec->channels));
197 DEBUG_PRINT(("freq=%d\n", spec->freq));
198
199 spec->format |= 0x8000; /* Audio is always signed */
200 if ((spec->format & 0x00ff)==16) {
201 spec->format |= 0x1000; /* Audio is always big endian */
202 spec->channels=2; /* 16 bits always stereo */
203 }
204
205 /* FIXME: check for an external clock */
206 MINTAUDIO_sfreq=1;
207 MINTAUDIO_nfreq=12;
208 for (i=MINTAUDIO_sfreq;i<MINTAUDIO_nfreq;i++) {
209 MINTAUDIO_hardfreq[i]=MASTERCLOCK_FALCON1/(MASTERPREDIV_FALCON*(i+1));
210 DEBUG_PRINT((DEBUG_NAME "calc:freq(%d)=%lu\n", i, MINTAUDIO_hardfreq[i]));
211 }
212
213 MINTAUDIO_numfreq=SDL_MintAudio_SearchFrequency(this, 1, spec->freq);
214 spec->freq=MINTAUDIO_hardfreq[MINTAUDIO_numfreq];
215
216 DEBUG_PRINT((DEBUG_NAME "obtained: %d bits, ",spec->format & 0x00ff));
217 DEBUG_PRINT(("signed=%d, ", ((spec->format & 0x8000)!=0)));
218 DEBUG_PRINT(("big endian=%d, ", ((spec->format & 0x8000)!=0)));
219 DEBUG_PRINT(("channels=%d, ", spec->channels));
220 DEBUG_PRINT(("freq=%d\n", spec->freq));
221
222 return 0;
223 }
224
225 static void Mint_InitAudio(_THIS, SDL_AudioSpec *spec)
226 {
227 int channels_mode;
228 void *buffer;
229
230 /* Stop currently playing sound */
231 Buffoper(0);
232
233 /* Set replay tracks */
234 Settracks(0,0);
235 Setmontracks(0);
236
237 /* Select replay format */
238 channels_mode=STEREO16;
239 switch (spec->format & 0xff) {
240 case 8:
241 if (spec->channels==2) {
242 channels_mode=STEREO8;
243 } else {
244 channels_mode=MONO8;
245 }
246 break;
247 }
248 if (Setmode(channels_mode)<0) {
249 DEBUG_PRINT((DEBUG_NAME "Setmode() failed\n"));
250 }
251
252 /* FIXME: select an external clock */
253
254 Devconnect(DMAPLAY, DAC, CLK25M, MINTAUDIO_numfreq, 1);
255 DEBUG_PRINT((DEBUG_NAME "25.175 MHz clock selected, prescaler %d\n", MINTAUDIO_numfreq));
256
257 /* Set buffer */
258 buffer = SDL_MintAudio_audiobuf[SDL_MintAudio_numbuf];
259 if (Setbuffer(0, buffer, buffer + spec->size)<0) {
260 DEBUG_PRINT((DEBUG_NAME "Setbuffer() failed\n"));
261 }
262
263 /* Install interrupt */
264 Jdisint(MFP_DMASOUND);
265 Xbtimer(XB_TIMERA, 8, 1, SDL_MintAudio_XbiosInterrupt);
266 Jenabint(MFP_DMASOUND);
267
268 if (Setinterrupt(SI_TIMERA, SI_PLAY)<0) {
269 DEBUG_PRINT((DEBUG_NAME "Setinterrupt() failed\n"));
270 }
271
272 /* Go */
273 Buffoper(SB_PLA_ENA|SB_PLA_RPT);
274 DEBUG_PRINT((DEBUG_NAME "hardware initialized\n"));
275 }
276
277 static int Mint_OpenAudio(_THIS, SDL_AudioSpec *spec)
278 {
279 /* Lock sound system */
280 if (Locksnd()!=1) {
281 SDL_SetError("Mint_OpenAudio: Audio system already in use");
282 return(-1);
283 }
284
285 SDL_MintAudio_device = this;
286
287 /* Check audio capabilities */
288 if (Mint_CheckAudio(this, spec)==-1) {
289 return -1;
290 }
291
292 SDL_CalculateAudioSpec(spec);
293
294 /* Allocate memory for audio buffers in DMA-able RAM */
295 spec->size = spec->samples;
296 spec->size *= spec->channels;
297 spec->size *= (spec->format & 0xFF)/8;
298
299 DEBUG_PRINT((DEBUG_NAME "buffer size=%d\n", spec->size));
300
301 SDL_MintAudio_audiobuf[0] = Atari_SysMalloc(spec->size *2, MX_STRAM);
302 if (SDL_MintAudio_audiobuf[0]==NULL) {
303 SDL_SetError("MINT_OpenAudio: Not enough memory for audio buffer");
304 return (-1);
305 }
306 SDL_MintAudio_audiobuf[1] = SDL_MintAudio_audiobuf[0] + spec->size ;
307 SDL_MintAudio_numbuf=0;
308 memset(SDL_MintAudio_audiobuf[0], spec->silence, spec->size *2);
309 SDL_MintAudio_audiosize = spec->size;
310 SDL_MintAudio_mutex = 0;
311
312 DEBUG_PRINT((DEBUG_NAME "buffer 0 at 0x%08x\n", SDL_MintAudio_audiobuf[0]));
313 DEBUG_PRINT((DEBUG_NAME "buffer 1 at 0x%08x\n", SDL_MintAudio_audiobuf[1]));
314
315 /* Setup audio hardware */
316 Mint_InitAudio(this, spec);
317
318 return(1); /* We don't use threaded audio */
319 }