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

Latest commit

 

History

History
319 lines (272 loc) · 9.03 KB

SDL_romaudio.c

File metadata and controls

319 lines (272 loc) · 9.03 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"
Mar 30, 2002
Mar 30, 2002
53
54
55
56
#pragma options align=power
static volatile SInt32 audio_is_locked = 0;
static volatile SInt32 need_to_mix = 0;
Apr 26, 2001
Apr 26, 2001
57
Jul 10, 2006
Jul 10, 2006
58
static UInt8 *buffer[2];
Apr 26, 2001
Apr 26, 2001
59
60
static volatile UInt32 running = 0;
static CmpSoundHeader header;
Mar 30, 2002
Mar 30, 2002
61
62
static volatile Uint32 fill_me = 0;
Oct 4, 2006
Oct 4, 2006
63
Jul 10, 2006
Jul 10, 2006
64
65
static void
mix_buffer(SDL_AudioDevice * audio, UInt8 * buffer)
Mar 30, 2002
Mar 30, 2002
66
{
Jul 10, 2006
Jul 10, 2006
67
if (!audio->paused) {
Feb 21, 2006
Feb 21, 2006
68
#ifdef __MACOSX__
Apr 13, 2002
Apr 13, 2002
69
70
SDL_mutexP(audio->mixer_lock);
#endif
Jul 10, 2006
Jul 10, 2006
71
if (audio->convert.needed) {
Apr 13, 2002
Apr 13, 2002
72
audio->spec.callback(audio->spec.userdata,
Jul 10, 2006
Jul 10, 2006
73
74
(Uint8 *) audio->convert.buf,
audio->convert.len);
Apr 13, 2002
Apr 13, 2002
75
SDL_ConvertAudio(&audio->convert);
Jul 10, 2006
Jul 10, 2006
76
77
if (audio->convert.len_cvt != audio->spec.size) {
/* Uh oh... probably crashes here */ ;
Mar 30, 2002
Mar 30, 2002
78
}
Feb 7, 2006
Feb 7, 2006
79
SDL_memcpy(buffer, audio->convert.buf, audio->convert.len_cvt);
Mar 30, 2002
Mar 30, 2002
80
} else {
Jul 10, 2006
Jul 10, 2006
81
82
audio->spec.callback(audio->spec.userdata, buffer,
audio->spec.size);
Mar 30, 2002
Mar 30, 2002
83
}
Feb 21, 2006
Feb 21, 2006
84
#ifdef __MACOSX__
Apr 13, 2002
Apr 13, 2002
85
86
SDL_mutexV(audio->mixer_lock);
#endif
Mar 30, 2002
Mar 30, 2002
87
88
}
Jul 10, 2006
Jul 10, 2006
89
DecrementAtomic((SInt32 *) & need_to_mix);
Mar 30, 2002
Mar 30, 2002
90
91
}
Jul 10, 2006
Jul 10, 2006
92
static void
Oct 3, 2006
Oct 3, 2006
93
SNDMGR_LockDevice(_THIS)
Mar 30, 2002
Mar 30, 2002
94
{
Jul 10, 2006
Jul 10, 2006
95
IncrementAtomic((SInt32 *) & audio_is_locked);
Mar 30, 2002
Mar 30, 2002
96
97
}
Jul 10, 2006
Jul 10, 2006
98
static void
Oct 3, 2006
Oct 3, 2006
99
SNDMGR_UnlockDevice(_THIS)
Mar 30, 2002
Mar 30, 2002
100
101
{
SInt32 oldval;
Jul 10, 2006
Jul 10, 2006
102
103
104
oldval = DecrementAtomic((SInt32 *) & audio_is_locked);
if (oldval != 1) /* != 1 means audio is still locked. */
Mar 30, 2002
Mar 30, 2002
105
106
107
return;
/* Did we miss the chance to mix in an interrupt? Do it now. */
Jul 10, 2006
Jul 10, 2006
108
if (BitAndAtomic(0xFFFFFFFF, (UInt32 *) & need_to_mix)) {
Mar 30, 2002
Mar 30, 2002
109
110
111
112
113
/*
* 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
114
mix_buffer(this, buffer[fill_me]);
Mar 30, 2002
Mar 30, 2002
115
116
}
}
Apr 26, 2001
Apr 26, 2001
117
Jul 10, 2006
Jul 10, 2006
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
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);
Oct 7, 2006
Oct 7, 2006
141
SDL_memset(buffer[fill_me], 0, audio->spec.size);
Jul 10, 2006
Jul 10, 2006
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/*
* 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
159
160
}
Jul 10, 2006
Jul 10, 2006
161
static int
Oct 3, 2006
Oct 3, 2006
162
SNDMGR_OpenDevice(_THIS, const char *devname, int iscapture)
Jul 10, 2006
Jul 10, 2006
163
{
Oct 1, 2006
Oct 1, 2006
164
165
SDL_AudioSpec *spec = &this->spec;
SndChannelPtr channel = NULL;
Jul 10, 2006
Jul 10, 2006
166
167
168
169
SndCallBackUPP callback;
int sample_bits;
int i;
long initOptions;
Apr 26, 2001
Apr 26, 2001
170
Oct 1, 2006
Oct 1, 2006
171
172
173
174
175
176
177
178
179
180
/* 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
181
/* Very few conversions are required, but... */
Apr 26, 2001
Apr 26, 2001
182
switch (spec->format) {
Jul 10, 2006
Jul 10, 2006
183
case AUDIO_S8:
Apr 26, 2001
Apr 26, 2001
184
185
spec->format = AUDIO_U8;
break;
Jul 10, 2006
Jul 10, 2006
186
case AUDIO_U16LSB:
Apr 26, 2001
Apr 26, 2001
187
188
spec->format = AUDIO_S16LSB;
break;
Jul 10, 2006
Jul 10, 2006
189
case AUDIO_U16MSB:
Apr 26, 2001
Apr 26, 2001
190
191
spec->format = AUDIO_S16MSB;
break;
Sep 1, 2006
Sep 1, 2006
192
193
194
case AUDIO_F32LSB:
spec->format = AUDIO_F32MSB;
break;
Apr 26, 2001
Apr 26, 2001
195
}
Oct 1, 2006
Oct 1, 2006
196
SDL_CalculateAudioSpec(&this->spec);
Jul 10, 2006
Jul 10, 2006
197
Apr 26, 2001
Apr 26, 2001
198
/* initialize bufferCmd header */
Oct 7, 2006
Oct 7, 2006
199
SDL_memset(&header, 0, sizeof(header));
Jul 10, 2006
Jul 10, 2006
200
callback = (SndCallBackUPP) NewSndCallBackUPP(callBackProc);
Apr 26, 2001
Apr 26, 2001
201
202
203
204
sample_bits = spec->size / spec->samples / spec->channels * 8;
#ifdef DEBUG_AUDIO
fprintf(stderr,
Jul 10, 2006
Jul 10, 2006
205
206
"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
207
#endif /* DEBUG_AUDIO */
Jul 10, 2006
Jul 10, 2006
208
Apr 26, 2001
Apr 26, 2001
209
header.numChannels = spec->channels;
Jul 10, 2006
Jul 10, 2006
210
211
212
213
214
header.sampleSize = sample_bits;
header.sampleRate = spec->freq << 16;
header.numFrames = spec->samples;
header.encode = cmpSH;
Apr 26, 2001
Apr 26, 2001
215
/* Note that we install the 16bitLittleEndian Converter if needed. */
Sep 1, 2006
Sep 1, 2006
216
if (spec->format == AUDIO_S16LSB) {
Apr 26, 2001
Apr 26, 2001
217
218
header.compressionID = fixedCompression;
header.format = k16BitLittleEndianFormat;
Sep 1, 2006
Sep 1, 2006
219
220
221
222
223
224
225
226
227
} 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
228
}
Jul 10, 2006
Jul 10, 2006
229
Apr 26, 2001
Apr 26, 2001
230
/* allocate 2 buffers */
Jul 10, 2006
Jul 10, 2006
231
for (i = 0; i < 2; i++) {
Oct 7, 2006
Oct 7, 2006
232
buffer[i] = (UInt8 *) SDL_malloc(sizeof(UInt8) * spec->size);
Jul 10, 2006
Jul 10, 2006
233
if (buffer[i] == NULL) {
Oct 3, 2006
Oct 3, 2006
234
SNDMGR_CloseDevice(this);
Jul 10, 2006
Jul 10, 2006
235
SDL_OutOfMemory();
Oct 1, 2006
Oct 1, 2006
236
return 0;
Jul 10, 2006
Jul 10, 2006
237
}
Oct 7, 2006
Oct 7, 2006
238
SDL_memset(buffer[i], 0, spec->size);
Jul 10, 2006
Jul 10, 2006
239
240
241
242
243
}
/* Create the sound manager channel */
channel = (SndChannelPtr) SDL_malloc(sizeof(*channel));
if (channel == NULL) {
Oct 3, 2006
Oct 3, 2006
244
SNDMGR_CloseDevice(this);
Apr 26, 2001
Apr 26, 2001
245
SDL_OutOfMemory();
Oct 1, 2006
Oct 1, 2006
246
return 0;
Apr 26, 2001
Apr 26, 2001
247
}
Oct 1, 2006
Oct 1, 2006
248
this->hidden->channel = channel;
Jul 10, 2006
Jul 10, 2006
249
if (spec->channels >= 2) {
Apr 26, 2001
Apr 26, 2001
250
251
252
253
initOptions = initStereo;
} else {
initOptions = initMono;
}
Jul 10, 2006
Jul 10, 2006
254
channel->userInfo = (long) this;
Apr 26, 2001
Apr 26, 2001
255
channel->qLength = 128;
Jul 10, 2006
Jul 10, 2006
256
if (SndNewChannel(&channel, sampledSynth, initOptions, callback) != noErr) {
Oct 3, 2006
Oct 3, 2006
257
SNDMGR_CloseDevice(this);
Apr 26, 2001
Apr 26, 2001
258
SDL_SetError("Unable to create audio channel");
Oct 1, 2006
Oct 1, 2006
259
return 0;
Apr 26, 2001
Apr 26, 2001
260
}
Jul 10, 2006
Jul 10, 2006
261
262
263
264
265
266
267
268
269
270
271
/* start playback */
{
SndCommand cmd;
cmd.cmd = callBackCmd;
cmd.param2 = 0;
running = 1;
SndDoCommand(channel, &cmd, 0);
}
return 1;
Apr 26, 2001
Apr 26, 2001
272
273
}
Jul 10, 2006
Jul 10, 2006
274
static void
Oct 3, 2006
Oct 3, 2006
275
SNDMGR_CloseDevice(_THIS)
Jul 10, 2006
Jul 10, 2006
276
277
278
279
280
{
int i;
running = 0;
Oct 1, 2006
Oct 1, 2006
281
282
283
if (this->hidden->channel) {
SndDisposeChannel(this->hidden->channel, true);
this->hidden->channel = NULL;
Jul 10, 2006
Jul 10, 2006
284
285
286
287
}
for (i = 0; i < 2; ++i) {
if (buffer[i]) {
Feb 7, 2006
Feb 7, 2006
288
SDL_free(buffer[i]);
Apr 26, 2001
Apr 26, 2001
289
290
291
buffer[i] = NULL;
}
}
Oct 1, 2006
Oct 1, 2006
292
293
SDL_free(this->hidden);
this->hidden = NULL;
Apr 26, 2001
Apr 26, 2001
294
295
}
Oct 6, 2006
Oct 6, 2006
296
297
298
299
300
301
302
303
304
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;
Oct 7, 2006
Oct 7, 2006
305
306
/* Mac OS X uses threaded audio, so normal thread code is okay */
#ifndef __MACOSX__
Oct 6, 2006
Oct 6, 2006
307
308
impl->LockDevice = SNDMGR_LockDevice;
impl->UnlockDevice = SNDMGR_UnlockDevice;
Oct 7, 2006
Oct 7, 2006
309
impl->SkipMixerLock = 1;
Oct 6, 2006
Oct 6, 2006
310
311
312
313
314
315
#endif
return 1;
}
AudioBootStrap SNDMGR_bootstrap = {
Oct 17, 2006
Oct 17, 2006
316
"sndmgr", SDL_MACOS_NAME " SoundManager", SNDMGR_Init, 0
Oct 6, 2006
Oct 6, 2006
317
318
};
Jul 10, 2006
Jul 10, 2006
319
/* vi: set ts=4 sw=4 expandtab: */