Skip to content
This repository has been archived by the owner on Feb 11, 2021. It is now read-only.

Latest commit

 

History

History
325 lines (276 loc) · 9.07 KB

SDL_romaudio.c

File metadata and controls

325 lines (276 loc) · 9.07 KB
 
Apr 26, 2001
Apr 26, 2001
1
2
/*
SDL - Simple DirectMedia Layer
Feb 1, 2006
Feb 1, 2006
3
Copyright (C) 1997-2006 Sam Lantinga
Apr 26, 2001
Apr 26, 2001
4
5
This library is free software; you can redistribute it and/or
Feb 1, 2006
Feb 1, 2006
6
modify it under the terms of the GNU Lesser General Public
Apr 26, 2001
Apr 26, 2001
7
License as published by the Free Software Foundation; either
Feb 1, 2006
Feb 1, 2006
8
version 2.1 of the License, or (at your option) any later version.
Apr 26, 2001
Apr 26, 2001
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
Feb 1, 2006
Feb 1, 2006
13
Lesser General Public License for more details.
Apr 26, 2001
Apr 26, 2001
14
Feb 1, 2006
Feb 1, 2006
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
Apr 26, 2001
Apr 26, 2001
18
19
Sam Lantinga
Dec 14, 2001
Dec 14, 2001
20
slouken@libsdl.org
Apr 26, 2001
Apr 26, 2001
21
*/
Feb 21, 2006
Feb 21, 2006
22
#include "SDL_config.h"
Apr 26, 2001
Apr 26, 2001
23
Oct 1, 2006
Oct 1, 2006
24
25
/* This should work on PowerPC and Intel Mac OS X, and Carbonized Mac OS 9. */
Sep 8, 2005
Sep 8, 2005
26
#if defined(__APPLE__) && defined(__MACH__)
Oct 1, 2006
Oct 1, 2006
27
# define SDL_MACOS_NAME "Mac OS X"
Sep 8, 2005
Sep 8, 2005
28
29
# include <Carbon/Carbon.h>
#elif TARGET_API_MAC_CARBON && (UNIVERSAL_INTERFACES_VERSION > 0x0335)
Oct 1, 2006
Oct 1, 2006
30
# define SDL_MACOS_NAME "Mac OS 9"
Apr 26, 2001
Apr 26, 2001
31
32
# include <Carbon.h>
#else
Oct 1, 2006
Oct 1, 2006
33
# define SDL_MACOS_NAME "Mac OS 9"
Jul 10, 2006
Jul 10, 2006
34
# include <Sound.h> /* SoundManager interface */
Apr 26, 2001
Apr 26, 2001
35
# include <Gestalt.h>
Mar 30, 2002
Mar 30, 2002
36
# include <DriverServices.h>
Apr 26, 2001
Apr 26, 2001
37
38
#endif
Sep 8, 2005
Sep 8, 2005
39
#if !defined(NewSndCallBackUPP) && (UNIVERSAL_INTERFACES_VERSION < 0x0335)
Jul 10, 2006
Jul 10, 2006
40
#if !defined(NewSndCallBackProc) /* avoid circular redefinition... */
Sep 8, 2005
Sep 8, 2005
41
42
#define NewSndCallBackUPP NewSndCallBackProc
#endif
Sep 8, 2005
Sep 8, 2005
43
44
45
#if !defined(NewSndCallBackUPP)
#define NewSndCallBackUPP NewSndCallBackProc
#endif
Sep 8, 2005
Sep 8, 2005
46
47
#endif
Apr 26, 2001
Apr 26, 2001
48
#include "SDL_audio.h"
Feb 16, 2006
Feb 16, 2006
49
50
#include "../SDL_audio_c.h"
#include "../SDL_sysaudio.h"
Apr 26, 2001
Apr 26, 2001
51
52
#include "SDL_romaudio.h"
Jul 10, 2006
Jul 10, 2006
53
static int
Oct 1, 2006
Oct 1, 2006
54
SNDMGR_Available(void)
Apr 26, 2001
Apr 26, 2001
55
{
Jul 10, 2006
Jul 10, 2006
56
return (1);
Apr 26, 2001
Apr 26, 2001
57
58
59
}
Mar 30, 2002
Mar 30, 2002
60
61
62
63
#pragma options align=power
static volatile SInt32 audio_is_locked = 0;
static volatile SInt32 need_to_mix = 0;
Apr 26, 2001
Apr 26, 2001
64
Jul 10, 2006
Jul 10, 2006
65
static UInt8 *buffer[2];
Apr 26, 2001
Apr 26, 2001
66
67
static volatile UInt32 running = 0;
static CmpSoundHeader header;
Mar 30, 2002
Mar 30, 2002
68
69
static volatile Uint32 fill_me = 0;
Oct 4, 2006
Oct 4, 2006
70
Jul 10, 2006
Jul 10, 2006
71
72
static void
mix_buffer(SDL_AudioDevice * audio, UInt8 * buffer)
Mar 30, 2002
Mar 30, 2002
73
{
Jul 10, 2006
Jul 10, 2006
74
if (!audio->paused) {
Feb 21, 2006
Feb 21, 2006
75
#ifdef __MACOSX__
Apr 13, 2002
Apr 13, 2002
76
77
SDL_mutexP(audio->mixer_lock);
#endif
Jul 10, 2006
Jul 10, 2006
78
if (audio->convert.needed) {
Apr 13, 2002
Apr 13, 2002
79
audio->spec.callback(audio->spec.userdata,
Jul 10, 2006
Jul 10, 2006
80
81
(Uint8 *) audio->convert.buf,
audio->convert.len);
Apr 13, 2002
Apr 13, 2002
82
SDL_ConvertAudio(&audio->convert);
Jul 10, 2006
Jul 10, 2006
83
84
if (audio->convert.len_cvt != audio->spec.size) {
/* Uh oh... probably crashes here */ ;
Mar 30, 2002
Mar 30, 2002
85
}
Feb 7, 2006
Feb 7, 2006
86
SDL_memcpy(buffer, audio->convert.buf, audio->convert.len_cvt);
Mar 30, 2002
Mar 30, 2002
87
} else {
Jul 10, 2006
Jul 10, 2006
88
89
audio->spec.callback(audio->spec.userdata, buffer,
audio->spec.size);
Mar 30, 2002
Mar 30, 2002
90
}
Feb 21, 2006
Feb 21, 2006
91
#ifdef __MACOSX__
Apr 13, 2002
Apr 13, 2002
92
93
SDL_mutexV(audio->mixer_lock);
#endif
Mar 30, 2002
Mar 30, 2002
94
95
}
Jul 10, 2006
Jul 10, 2006
96
DecrementAtomic((SInt32 *) & need_to_mix);
Mar 30, 2002
Mar 30, 2002
97
98
}
Jul 10, 2006
Jul 10, 2006
99
static void
Oct 3, 2006
Oct 3, 2006
100
SNDMGR_LockDevice(_THIS)
Mar 30, 2002
Mar 30, 2002
101
{
Jul 10, 2006
Jul 10, 2006
102
IncrementAtomic((SInt32 *) & audio_is_locked);
Mar 30, 2002
Mar 30, 2002
103
104
}
Jul 10, 2006
Jul 10, 2006
105
static void
Oct 3, 2006
Oct 3, 2006
106
SNDMGR_UnlockDevice(_THIS)
Mar 30, 2002
Mar 30, 2002
107
108
{
SInt32 oldval;
Jul 10, 2006
Jul 10, 2006
109
110
111
oldval = DecrementAtomic((SInt32 *) & audio_is_locked);
if (oldval != 1) /* != 1 means audio is still locked. */
Mar 30, 2002
Mar 30, 2002
112
113
114
return;
/* Did we miss the chance to mix in an interrupt? Do it now. */
Jul 10, 2006
Jul 10, 2006
115
if (BitAndAtomic(0xFFFFFFFF, (UInt32 *) & need_to_mix)) {
Mar 30, 2002
Mar 30, 2002
116
117
118
119
120
/*
* Note that this could be a problem if you missed an interrupt
* while the audio was locked, and get preempted by a second
* interrupt here, but that means you locked for way too long anyhow.
*/
Jul 10, 2006
Jul 10, 2006
121
mix_buffer(this, buffer[fill_me]);
Mar 30, 2002
Mar 30, 2002
122
123
}
}
Apr 26, 2001
Apr 26, 2001
124
Jul 10, 2006
Jul 10, 2006
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
static void
callBackProc(SndChannel * chan, SndCommand * cmd_passed)
{
UInt32 play_me;
SndCommand cmd;
SDL_AudioDevice *audio = (SDL_AudioDevice *) chan->userInfo;
IncrementAtomic((SInt32 *) & need_to_mix);
fill_me = cmd_passed->param2; /* buffer that has just finished playing, so fill it */
play_me = !fill_me; /* filled buffer to play _now_ */
if (!audio->enabled) {
return;
}
/* queue previously mixed buffer for playback. */
header.samplePtr = (Ptr) buffer[play_me];
cmd.cmd = bufferCmd;
cmd.param1 = 0;
cmd.param2 = (long) &header;
SndDoCommand(chan, &cmd, 0);
memset(buffer[fill_me], 0, audio->spec.size);
/*
* if audio device isn't locked, mix the next buffer to be queued in
* the memory block that just finished playing.
*/
if (!BitAndAtomic(0xFFFFFFFF, (UInt32 *) & audio_is_locked)) {
mix_buffer(audio, buffer[fill_me]);
}
/* set this callback to run again when current buffer drains. */
if (running) {
cmd.cmd = callBackCmd;
cmd.param1 = 0;
cmd.param2 = play_me;
SndDoCommand(chan, &cmd, 0);
}
Apr 26, 2001
Apr 26, 2001
166
167
}
Jul 10, 2006
Jul 10, 2006
168
static int
Oct 3, 2006
Oct 3, 2006
169
SNDMGR_OpenDevice(_THIS, const char *devname, int iscapture)
Jul 10, 2006
Jul 10, 2006
170
{
Oct 1, 2006
Oct 1, 2006
171
172
SDL_AudioSpec *spec = &this->spec;
SndChannelPtr channel = NULL;
Jul 10, 2006
Jul 10, 2006
173
174
175
176
SndCallBackUPP callback;
int sample_bits;
int i;
long initOptions;
Apr 26, 2001
Apr 26, 2001
177
Oct 1, 2006
Oct 1, 2006
178
179
180
181
182
183
184
185
186
187
/* Initialize all variables that we clean on shutdown */
this->hidden = (struct SDL_PrivateAudioData *)
SDL_malloc((sizeof *this->hidden));
if (this->hidden == NULL) {
SDL_OutOfMemory();
return 0;
}
SDL_memset(this->hidden, 0, (sizeof *this->hidden));
/* !!! FIXME: iterate through format matrix... */
Jul 10, 2006
Jul 10, 2006
188
/* Very few conversions are required, but... */
Apr 26, 2001
Apr 26, 2001
189
switch (spec->format) {
Jul 10, 2006
Jul 10, 2006
190
case AUDIO_S8:
Apr 26, 2001
Apr 26, 2001
191
192
spec->format = AUDIO_U8;
break;
Jul 10, 2006
Jul 10, 2006
193
case AUDIO_U16LSB:
Apr 26, 2001
Apr 26, 2001
194
195
spec->format = AUDIO_S16LSB;
break;
Jul 10, 2006
Jul 10, 2006
196
case AUDIO_U16MSB:
Apr 26, 2001
Apr 26, 2001
197
198
spec->format = AUDIO_S16MSB;
break;
Sep 1, 2006
Sep 1, 2006
199
200
201
case AUDIO_F32LSB:
spec->format = AUDIO_F32MSB;
break;
Apr 26, 2001
Apr 26, 2001
202
}
Oct 1, 2006
Oct 1, 2006
203
SDL_CalculateAudioSpec(&this->spec);
Jul 10, 2006
Jul 10, 2006
204
Apr 26, 2001
Apr 26, 2001
205
/* initialize bufferCmd header */
Jul 10, 2006
Jul 10, 2006
206
207
memset(&header, 0, sizeof(header));
callback = (SndCallBackUPP) NewSndCallBackUPP(callBackProc);
Apr 26, 2001
Apr 26, 2001
208
209
210
211
sample_bits = spec->size / spec->samples / spec->channels * 8;
#ifdef DEBUG_AUDIO
fprintf(stderr,
Jul 10, 2006
Jul 10, 2006
212
213
"Audio format 0x%x, channels = %d, sample_bits = %d, frequency = %d\n",
spec->format, spec->channels, sample_bits, spec->freq);
Apr 26, 2001
Apr 26, 2001
214
#endif /* DEBUG_AUDIO */
Jul 10, 2006
Jul 10, 2006
215
Apr 26, 2001
Apr 26, 2001
216
header.numChannels = spec->channels;
Jul 10, 2006
Jul 10, 2006
217
218
219
220
221
header.sampleSize = sample_bits;
header.sampleRate = spec->freq << 16;
header.numFrames = spec->samples;
header.encode = cmpSH;
Apr 26, 2001
Apr 26, 2001
222
/* Note that we install the 16bitLittleEndian Converter if needed. */
Sep 1, 2006
Sep 1, 2006
223
if (spec->format == AUDIO_S16LSB) {
Apr 26, 2001
Apr 26, 2001
224
225
header.compressionID = fixedCompression;
header.format = k16BitLittleEndianFormat;
Sep 1, 2006
Sep 1, 2006
226
227
228
229
230
231
232
233
234
} else if (spec->format == AUDIO_S32MSB) {
header.compressionID = fixedCompression;
header.format = k32BitFormat;
} else if (spec->format == AUDIO_S32LSB) {
header.compressionID = fixedCompression;
header.format = k32BitLittleEndianFormat;
} else if (spec->format == AUDIO_F32MSB) {
header.compressionID = fixedCompression;
header.format = kFloat32Format;
Apr 26, 2001
Apr 26, 2001
235
}
Jul 10, 2006
Jul 10, 2006
236
Apr 26, 2001
Apr 26, 2001
237
/* allocate 2 buffers */
Jul 10, 2006
Jul 10, 2006
238
239
240
for (i = 0; i < 2; i++) {
buffer[i] = (UInt8 *) malloc(sizeof(UInt8) * spec->size);
if (buffer[i] == NULL) {
Oct 3, 2006
Oct 3, 2006
241
SNDMGR_CloseDevice(this);
Jul 10, 2006
Jul 10, 2006
242
SDL_OutOfMemory();
Oct 1, 2006
Oct 1, 2006
243
return 0;
Jul 10, 2006
Jul 10, 2006
244
245
246
247
248
249
250
}
memset(buffer[i], 0, spec->size);
}
/* Create the sound manager channel */
channel = (SndChannelPtr) SDL_malloc(sizeof(*channel));
if (channel == NULL) {
Oct 3, 2006
Oct 3, 2006
251
SNDMGR_CloseDevice(this);
Apr 26, 2001
Apr 26, 2001
252
SDL_OutOfMemory();
Oct 1, 2006
Oct 1, 2006
253
return 0;
Apr 26, 2001
Apr 26, 2001
254
}
Oct 1, 2006
Oct 1, 2006
255
this->hidden->channel = channel;
Jul 10, 2006
Jul 10, 2006
256
if (spec->channels >= 2) {
Apr 26, 2001
Apr 26, 2001
257
258
259
260
initOptions = initStereo;
} else {
initOptions = initMono;
}
Jul 10, 2006
Jul 10, 2006
261
channel->userInfo = (long) this;
Apr 26, 2001
Apr 26, 2001
262
channel->qLength = 128;
Jul 10, 2006
Jul 10, 2006
263
if (SndNewChannel(&channel, sampledSynth, initOptions, callback) != noErr) {
Oct 3, 2006
Oct 3, 2006
264
SNDMGR_CloseDevice(this);
Apr 26, 2001
Apr 26, 2001
265
SDL_SetError("Unable to create audio channel");
Oct 1, 2006
Oct 1, 2006
266
return 0;
Apr 26, 2001
Apr 26, 2001
267
}
Jul 10, 2006
Jul 10, 2006
268
269
270
271
272
273
274
275
276
277
278
/* start playback */
{
SndCommand cmd;
cmd.cmd = callBackCmd;
cmd.param2 = 0;
running = 1;
SndDoCommand(channel, &cmd, 0);
}
return 1;
Apr 26, 2001
Apr 26, 2001
279
280
}
Jul 10, 2006
Jul 10, 2006
281
static void
Oct 3, 2006
Oct 3, 2006
282
SNDMGR_CloseDevice(_THIS)
Jul 10, 2006
Jul 10, 2006
283
284
285
286
287
{
int i;
running = 0;
Oct 1, 2006
Oct 1, 2006
288
289
290
if (this->hidden->channel) {
SndDisposeChannel(this->hidden->channel, true);
this->hidden->channel = NULL;
Jul 10, 2006
Jul 10, 2006
291
292
293
294
}
for (i = 0; i < 2; ++i) {
if (buffer[i]) {
Feb 7, 2006
Feb 7, 2006
295
SDL_free(buffer[i]);
Apr 26, 2001
Apr 26, 2001
296
297
298
buffer[i] = NULL;
}
}
Oct 1, 2006
Oct 1, 2006
299
300
SDL_free(this->hidden);
this->hidden = NULL;
Apr 26, 2001
Apr 26, 2001
301
302
}
Oct 6, 2006
Oct 6, 2006
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
static int
SNDMGR_Init(SDL_AudioDriverImpl *impl)
{
/* Set the function pointers */
impl->OpenDevice = SNDMGR_OpenDevice;
impl->CloseDevice = SNDMGR_CloseDevice;
impl->ProvidesOwnCallbackThread = 1;
impl->OnlyHasDefaultOutputDevice = 1;
#ifndef __MACOSX__ /* Mac OS X uses threaded audio, so normal thread code is okay */
impl->LockDevice = SNDMGR_LockDevice;
impl->UnlockDevice = SNDMGR_UnlockDevice;
#endif
return 1;
}
AudioBootStrap SNDMGR_bootstrap = {
"sndmgr", SDL_MACOS_NAME " SoundManager",
SNDMGR_Available, SNDMGR_Init, 0
};
Jul 10, 2006
Jul 10, 2006
325
/* vi: set ts=4 sw=4 expandtab: */