This repository has been archived by the owner on Feb 11, 2021. It is now read-only.
/
SDL_ahiaudio.c
357 lines (286 loc) · 9.81 KB
1
2
/*
SDL - Simple DirectMedia Layer
3
Copyright (C) 1997-2006 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
11
12
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
Lesser General Public License for more details.
14
15
16
17
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
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
25
/* Allow access to a raw mixing buffer (for AmigaOS) */
26
#include "SDL_audio.h"
27
#include "../SDL_audio_c.h"
28
#include "SDL_ahiaudio.h"
29
30
/* Audio driver functions */
31
static int AHI_OpenAudio(_THIS, SDL_AudioSpec * spec);
32
33
34
35
36
37
static void AHI_WaitAudio(_THIS);
static void AHI_PlayAudio(_THIS);
static Uint8 *AHI_GetAudioBuf(_THIS);
static void AHI_CloseAudio(_THIS);
#ifndef __SASC
38
39
#define mymalloc(x) AllocVec(x,MEMF_PUBLIC)
#define myfree FreeVec
40
#else
41
42
#define mymalloc malloc
#define myfree free
43
44
45
46
#endif
/* Audio driver bootstrap functions */
47
48
static int
Audio_Available(void)
49
{
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
int ok = 0;
struct MsgPort *p;
struct AHIRequest *req;
if (p = CreateMsgPort()) {
if (req =
(struct AHIRequest *) CreateIORequest(p,
sizeof(struct
AHIRequest))) {
req->ahir_Version = 4;
if (!OpenDevice(AHINAME, 0, (struct IORequest *) req, NULL)) {
D(bug("AHI available.\n"));
ok = 1;
CloseDevice((struct IORequest *) req);
}
DeleteIORequest((struct IORequest *) req);
}
DeleteMsgPort(p);
}
D(if (!ok) bug("AHI not available\n"));
return ok;
73
74
}
75
76
static void
Audio_DeleteDevice(SDL_AudioDevice * device)
77
{
78
79
SDL_free(device->hidden);
SDL_free(device);
80
81
}
82
83
static SDL_AudioDevice *
Audio_CreateDevice(int devindex)
84
{
85
SDL_AudioDevice *this;
86
87
#ifndef NO_AMIGADEBUG
88
D(bug("AHI created...\n"));
89
90
#endif
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
/* Initialize all variables that we clean on shutdown */
this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice));
if (this) {
SDL_memset(this, 0, (sizeof *this));
this->hidden = (struct SDL_PrivateAudioData *)
SDL_malloc((sizeof *this->hidden));
}
if ((this == NULL) || (this->hidden == NULL)) {
SDL_OutOfMemory();
if (this) {
SDL_free(this);
}
return (0);
}
SDL_memset(this->hidden, 0, (sizeof *this->hidden));
/* Set the function pointers */
this->OpenAudio = AHI_OpenAudio;
this->WaitAudio = AHI_WaitAudio;
this->PlayAudio = AHI_PlayAudio;
this->GetAudioBuf = AHI_GetAudioBuf;
this->CloseAudio = AHI_CloseAudio;
this->free = Audio_DeleteDevice;
return this;
117
118
119
}
AudioBootStrap AHI_bootstrap = {
120
"AHI", Audio_Available, Audio_CreateDevice
121
122
123
};
124
125
void static
AHI_WaitAudio(_THIS)
126
{
127
128
129
130
if (!CheckIO((struct IORequest *) audio_req[current_buffer])) {
WaitIO((struct IORequest *) audio_req[current_buffer]);
// AbortIO((struct IORequest *)audio_req[current_buffer]);
}
131
132
}
133
134
static void
AHI_PlayAudio(_THIS)
135
{
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
if (playing > 1)
WaitIO((struct IORequest *) audio_req[current_buffer]);
/* Write the audio data out */
audio_req[current_buffer]->ahir_Std.io_Message.mn_Node.ln_Pri = 60;
audio_req[current_buffer]->ahir_Std.io_Data = mixbuf[current_buffer];
audio_req[current_buffer]->ahir_Std.io_Length = this->hidden->size;
audio_req[current_buffer]->ahir_Std.io_Offset = 0;
audio_req[current_buffer]->ahir_Std.io_Command = CMD_WRITE;
audio_req[current_buffer]->ahir_Frequency = this->hidden->freq;
audio_req[current_buffer]->ahir_Volume = 0x10000;
audio_req[current_buffer]->ahir_Type = this->hidden->type;
audio_req[current_buffer]->ahir_Position = 0x8000;
audio_req[current_buffer]->ahir_Link =
(playing > 0 ? audio_req[current_buffer ^ 1] : NULL);
SendIO((struct IORequest *) audio_req[current_buffer]);
current_buffer ^= 1;
playing++;
156
157
}
158
159
static Uint8 *
AHI_GetAudioBuf(_THIS)
160
{
161
return (mixbuf[current_buffer]);
162
163
}
164
165
static void
AHI_CloseAudio(_THIS)
166
{
167
D(bug("Closing audio...\n"));
168
169
playing = 0;
170
171
172
173
if (audio_req[0]) {
if (audio_req[1]) {
D(bug("Break req[1]...\n"));
174
175
176
177
AbortIO((struct IORequest *) audio_req[1]);
WaitIO((struct IORequest *) audio_req[1]);
}
178
179
D(bug("Break req[0]...\n"));
180
181
182
AbortIO((struct IORequest *) audio_req[0]);
WaitIO((struct IORequest *) audio_req[0]);
183
184
185
186
187
188
if (audio_req[1]) {
D(bug("Break AGAIN req[1]...\n"));
AbortIO((struct IORequest *) audio_req[1]);
WaitIO((struct IORequest *) audio_req[1]);
}
189
190
// Double abort to be sure to break the dbuffering process.
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
SDL_Delay(200);
D(bug("Reqs breaked, closing device...\n"));
CloseDevice((struct IORequest *) audio_req[0]);
D(bug("Device closed, freeing memory...\n"));
myfree(audio_req[1]);
D(bug("Memory freed, deleting IOReq...\n"));
DeleteIORequest((struct IORequest *) audio_req[0]);
audio_req[0] = audio_req[1] = NULL;
}
D(bug("Freeing mixbuf[0]...\n"));
if (mixbuf[0] != NULL) {
myfree(mixbuf[0]);
// SDL_FreeAudioMem(mixbuf[0]);
mixbuf[0] = NULL;
}
D(bug("Freeing mixbuf[1]...\n"));
if (mixbuf[1] != NULL) {
myfree(mixbuf[1]);
// SDL_FreeAudioMem(mixbuf[1]);
mixbuf[1] = NULL;
}
D(bug("Freeing audio_port...\n"));
if (audio_port != NULL) {
DeleteMsgPort(audio_port);
audio_port = NULL;
}
D(bug("...done!\n"));
223
224
}
225
226
227
228
static int
AHI_OpenAudio(_THIS, SDL_AudioSpec * spec)
{
// int width;
229
SDL_AudioFormat test_format = SDL_FirstAudioFormat(spec->format);
230
231
232
233
D(bug("AHI opening...\n"));
/* Determine the audio parameters from the AudioSpec */
234
while (test_format) {
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
switch (test_format) {
case AUDIO_S8:
D(bug("AUDIO_S8...\n"));
spec->format = AUDIO_S8;
this->hidden->bytespersample = 1;
if (spec->channels < 2)
this->hidden->type = AHIST_M8S;
else
this->hidden->type = AHIST_S8S;
break;
case AUDIO_S16MSB:
D(bug("AUDIO_S16MSB...\n"));
spec->format = AUDIO_S16MSB;
this->hidden->bytespersample = 2;
if (spec->channels < 2)
this->hidden->type = AHIST_M16S;
else
this->hidden->type = AHIST_S16S;
break;
case AUDIO_S32MSB:
D(bug("AUDIO_S32MSB...\n"));
spec->format = AUDIO_S32MSB;
this->hidden->bytespersample = 4;
if (spec->channels < 2)
this->hidden->type = AHIST_M32S;
else
this->hidden->type = AHIST_S32S;
break;
default:
test_format = SDL_NextAudioFormat();
break;
269
}
270
}
271
272
if (!test_format) { /* shouldn't happen, but just in case... */
273
274
SDL_SetError("Unsupported audio format");
return (-1);
275
276
}
277
278
if (spec->channels > 2) {
spec->channels = 2; /* will convert at higher level. */
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
}
D(bug("Before CalculateAudioSpec\n"));
/* Update the fragment size as size in bytes */
SDL_CalculateAudioSpec(spec);
D(bug("Before CreateMsgPort\n"));
if (!(audio_port = CreateMsgPort())) {
SDL_SetError("Unable to create a MsgPort");
return -1;
}
D(bug("Before CreateIORequest\n"));
if (!
(audio_req[0] =
(struct AHIRequest *) CreateIORequest(audio_port,
sizeof(struct AHIRequest)))) {
SDL_SetError("Unable to create an AHIRequest");
DeleteMsgPort(audio_port);
return -1;
}
audio_req[0]->ahir_Version = 4;
if (OpenDevice(AHINAME, 0, (struct IORequest *) audio_req[0], NULL)) {
SDL_SetError("Unable to open AHI device!\n");
DeleteIORequest((struct IORequest *) audio_req[0]);
DeleteMsgPort(audio_port);
return -1;
}
D(bug("AFTER opendevice\n"));
/* Set output frequency and size */
this->hidden->freq = spec->freq;
this->hidden->size = spec->size;
D(bug("Before buffer allocation\n"));
/* Allocate mixing buffer */
mixbuf[0] = (Uint8 *) mymalloc(spec->size);
mixbuf[1] = (Uint8 *) mymalloc(spec->size);
D(bug("Before audio_req allocation\n"));
if (!(audio_req[1] = mymalloc(sizeof(struct AHIRequest)))) {
SDL_OutOfMemory();
return (-1);
}
D(bug("Before audio_req memcpy\n"));
SDL_memcpy(audio_req[1], audio_req[0], sizeof(struct AHIRequest));
if (mixbuf[0] == NULL || mixbuf[1] == NULL) {
SDL_OutOfMemory();
return (-1);
}
D(bug("Before mixbuf memset\n"));
SDL_memset(mixbuf[0], spec->silence, spec->size);
SDL_memset(mixbuf[1], spec->silence, spec->size);
current_buffer = 0;
playing = 0;
D(bug
("AHI opened: freq:%ld mixbuf:%lx/%lx buflen:%ld bits:%ld channels:%ld\n",
spec->freq, mixbuf[0], mixbuf[1], spec->size,
this->hidden->bytespersample * 8, spec->channels));
/* We're ready to rock and roll. :-) */
return (0);
355
}
356
357
/* vi: set ts=4 sw=4 expandtab: */