Mercurial > sdl-ios-xcode
annotate src/audio/macrom/SDL_romaudio.c @ 942:41a59de7f2ed
Here are patches for SDL12 and SDL_mixer for 4 or 6 channel
surround sound on Linux using the Alsa driver. To use them, naturally
you need a sound card that will do 4 or 6 channels and probably also a
recent version of the Alsa drivers and library. Since the only SDL
output driver that knows about surround sound is the Alsa driver,
you���ll want to choose it, using:
export SDL_AUDIODRIVER=alsa
There are no syntactic changes to the programming API. No new
library calls, no differences in arguments.
There are two semantic changes:
(1) For library calls with number of channels as an argument, formerly
you could use only 1 or 2 for the number of channels. Now you
can also use 4 or 6.
(2) The two "left" and "right" arguments to Mix_SetPanning, for the
case of 4 or 6 channels, no longer simply control the volumes of
the left and right channels. Now the "left" argument is converted
to an angle and Mix_SetPosition is called, and the "right" argu-
ment is ignored.
With two exceptions, so far as I know, the modified SDL12 and
SDL_mixer work the same way as the original versions, when opened for
1 or 2 channel output. The two exceptions are bugs which I fixed.
Well, the first, anyway, is a bug for sure. When rate conversions up
or down by a factor of two are applied (in src/audio/SDL_audiocvt.c),
streams with different numbers of channels (that is, mono and stereo)
are treated the same way: either each sample is copied or every other
sample is omitted. This is ok for mono, but for stereo, it is frames
that should be copied or omitted, where by "frame" I mean a portion of
the stream containing one sample for each channel. (In the SDL source,
confusingly, sometimes frames are called "samples".) So for these
rate conversions, stereo streams have to be treated differently, and
they are, in my modified version.
The other problem that might be characterized as a bug arises
when SDL_mixer is passed a multichannel chunk which does not have an
integral number of frames. Due to the way the effect_position code
loops over frames, when the chunk ends with a partial frame, memory
outside the chunk buffer will be accessed. In the case of stereo,
it���s possible that because malloc may give more memory than requested,
this potential problem never actually causes a segment fault. I don���t
know. For 6 channel chunks, I do know, and it does cause segment
faults.
If SDL_mixer is passed defective chunks and this causes a segment
fault, arguably, that���s not a bug in SDL_mixer. Still, whether or not
it counts as a bug, it���s easy to protect against, so why not? I added
code in mixer.c to discard any partial frame at the end of a chunk.
Then what about when SDL or SDL_mixer is opened for 4 or 6 chan-
nel output? What happens with the parts of the current library
designed for stereo? I don���t know whether I���ve covered all the bases,
but I���ve tried:
(1) For playing 2 channel waves, or other cases where SDL knows it has
to match up a 2 channel source with a 4 or 6 channel output, I���ve
added code in SDL_audiocvt.c to make the necessary conversions.
(2) For playing midis using timidity, I���ve converted timidity to do 4
or 6 channel output, upon request.
(3) For playing mods using mikmod, I put ad hoc code in music.c to
convert the stereo output that mikmod produces to 4 or 6 chan-
nels. Obviously it would be better to change the mikmod code to
mix down into 4 or 6 channels, but I have a hard time following
the code in mikmod, so I didn���t do that.
(4) For playing mp3s, I put ad hoc code in smpeg to copy channels in
the case when 4 or 6 channel output is needed.
(5) There seems to be no problem with .ogg files - stereo .oggs can be
up converted as .wavs are.
(6) The effect_position code in SDL_mixer is now generalized to in-
clude the cases of 4 and 6 channel streams.
I���ve done a very limited amount of compatibility testing for some
of the games using SDL I happen to have. For details, see the file
TESTS.
I���ve put into a separate archive, Surround-SDL-testfiles.tgz, a
couple of 6 channel wave files for testing and a 6 channel ogg file.
If you have the right hardware and version of Alsa, you should be able
to play the wave files with the Alsa utility aplay (and hear all
channels, except maybe lfe, for chan-id.wav, since it���s rather faint).
Don���t expect aplay to give good sound, though. There���s something
wrong with the current version of aplay.
The canyon.ogg file is to test loading of 6 channel oggs. After
patching and compiling, you can play it with playmus. (My version of
ogg123 will not play it, and I had to patch mplayer to get it to play
6 channel oggs.)
Greg Lee <greg@ling.lll.hawaii.edu>
Thus, July 1, 2004
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Sat, 21 Aug 2004 12:27:02 +0000 |
parents | b8d311d90021 |
children | 609c060fd2a2 |
rev | line source |
---|---|
0 | 1 /* |
2 SDL - Simple DirectMedia Layer | |
769
b8d311d90021
Updated copyright information for 2004 (Happy New Year!)
Sam Lantinga <slouken@libsdl.org>
parents:
348
diff
changeset
|
3 Copyright (C) 1997-2004 Sam Lantinga |
0 | 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 | |
252
e8157fcb3114
Updated the source with the correct e-mail address
Sam Lantinga <slouken@libsdl.org>
parents:
47
diff
changeset
|
20 slouken@libsdl.org |
0 | 21 */ |
22 | |
23 #ifdef SAVE_RCSID | |
24 static char rcsid = | |
25 "@(#) $Id$"; | |
26 #endif | |
27 | |
28 #if TARGET_API_MAC_CARBON | |
29 # include <Carbon.h> | |
30 #else | |
31 # include <Sound.h> /* SoundManager interface */ | |
32 # include <Gestalt.h> | |
323
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
33 # include <DriverServices.h> |
0 | 34 #endif |
35 | |
36 #include <stdlib.h> | |
37 #include <stdio.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 #include "SDL_romaudio.h" | |
45 | |
46 /* Audio driver functions */ | |
47 | |
48 static void Mac_CloseAudio(_THIS); | |
49 static int Mac_OpenAudio(_THIS, SDL_AudioSpec *spec); | |
323
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
50 static void Mac_LockAudio(_THIS); |
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
51 static void Mac_UnlockAudio(_THIS); |
0 | 52 |
53 /* Audio driver bootstrap functions */ | |
54 | |
55 | |
56 static int Audio_Available(void) | |
57 { | |
58 return(1); | |
59 } | |
60 | |
61 static void Audio_DeleteDevice(SDL_AudioDevice *device) | |
62 { | |
63 free(device->hidden); | |
64 free(device); | |
65 } | |
66 | |
67 static SDL_AudioDevice *Audio_CreateDevice(int devindex) | |
68 { | |
69 SDL_AudioDevice *this; | |
70 | |
71 /* Initialize all variables that we clean on shutdown */ | |
72 this = (SDL_AudioDevice *)malloc(sizeof(SDL_AudioDevice)); | |
73 if ( this ) { | |
74 memset(this, 0, (sizeof *this)); | |
75 this->hidden = (struct SDL_PrivateAudioData *) | |
76 malloc((sizeof *this->hidden)); | |
77 } | |
78 if ( (this == NULL) || (this->hidden == NULL) ) { | |
79 SDL_OutOfMemory(); | |
80 if ( this ) { | |
81 free(this); | |
82 } | |
83 return(0); | |
84 } | |
85 memset(this->hidden, 0, (sizeof *this->hidden)); | |
86 | |
87 /* Set the function pointers */ | |
88 this->OpenAudio = Mac_OpenAudio; | |
89 this->CloseAudio = Mac_CloseAudio; | |
323
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
90 this->LockAudio = Mac_LockAudio; |
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
91 this->UnlockAudio = Mac_UnlockAudio; |
0 | 92 this->free = Audio_DeleteDevice; |
93 | |
348
25809353f877
Re-added MacOS X audio locking
Sam Lantinga <slouken@libsdl.org>
parents:
324
diff
changeset
|
94 #ifdef MACOSX /* MacOS X uses threaded audio, so normal thread code is okay */ |
25809353f877
Re-added MacOS X audio locking
Sam Lantinga <slouken@libsdl.org>
parents:
324
diff
changeset
|
95 this->LockAudio = NULL; |
25809353f877
Re-added MacOS X audio locking
Sam Lantinga <slouken@libsdl.org>
parents:
324
diff
changeset
|
96 this->UnlockAudio = NULL; |
25809353f877
Re-added MacOS X audio locking
Sam Lantinga <slouken@libsdl.org>
parents:
324
diff
changeset
|
97 #endif |
0 | 98 return this; |
99 } | |
100 | |
101 AudioBootStrap SNDMGR_bootstrap = { | |
102 "sndmgr", "MacOS SoundManager 3.0", | |
103 Audio_Available, Audio_CreateDevice | |
104 }; | |
105 | |
323
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
106 #if defined(TARGET_API_MAC_CARBON) || defined(USE_RYANS_SOUNDCODE) |
348
25809353f877
Re-added MacOS X audio locking
Sam Lantinga <slouken@libsdl.org>
parents:
324
diff
changeset
|
107 /* This works correctly on MacOS X */ |
323
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
108 |
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
109 #pragma options align=power |
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
110 |
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
111 static volatile SInt32 audio_is_locked = 0; |
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
112 static volatile SInt32 need_to_mix = 0; |
0 | 113 |
114 static UInt8 *buffer[2]; | |
115 static volatile UInt32 running = 0; | |
116 static CmpSoundHeader header; | |
323
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
117 static volatile Uint32 fill_me = 0; |
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
118 |
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
119 static void mix_buffer(SDL_AudioDevice *audio, UInt8 *buffer) |
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
120 { |
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
121 if ( ! audio->paused ) { |
348
25809353f877
Re-added MacOS X audio locking
Sam Lantinga <slouken@libsdl.org>
parents:
324
diff
changeset
|
122 #ifdef MACOSX |
25809353f877
Re-added MacOS X audio locking
Sam Lantinga <slouken@libsdl.org>
parents:
324
diff
changeset
|
123 SDL_mutexP(audio->mixer_lock); |
25809353f877
Re-added MacOS X audio locking
Sam Lantinga <slouken@libsdl.org>
parents:
324
diff
changeset
|
124 #endif |
323
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
125 if ( audio->convert.needed ) { |
348
25809353f877
Re-added MacOS X audio locking
Sam Lantinga <slouken@libsdl.org>
parents:
324
diff
changeset
|
126 audio->spec.callback(audio->spec.userdata, |
323
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
127 (Uint8 *)audio->convert.buf,audio->convert.len); |
348
25809353f877
Re-added MacOS X audio locking
Sam Lantinga <slouken@libsdl.org>
parents:
324
diff
changeset
|
128 SDL_ConvertAudio(&audio->convert); |
323
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
129 if ( audio->convert.len_cvt != audio->spec.size ) { |
348
25809353f877
Re-added MacOS X audio locking
Sam Lantinga <slouken@libsdl.org>
parents:
324
diff
changeset
|
130 /* Uh oh... probably crashes here */; |
323
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
131 } |
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
132 memcpy(buffer, audio->convert.buf, audio->convert.len_cvt); |
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
133 } else { |
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
134 audio->spec.callback(audio->spec.userdata, buffer, audio->spec.size); |
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
135 } |
348
25809353f877
Re-added MacOS X audio locking
Sam Lantinga <slouken@libsdl.org>
parents:
324
diff
changeset
|
136 #ifdef MACOSX |
25809353f877
Re-added MacOS X audio locking
Sam Lantinga <slouken@libsdl.org>
parents:
324
diff
changeset
|
137 SDL_mutexV(audio->mixer_lock); |
25809353f877
Re-added MacOS X audio locking
Sam Lantinga <slouken@libsdl.org>
parents:
324
diff
changeset
|
138 #endif |
323
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
139 } |
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
140 |
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
141 DecrementAtomic((SInt32 *) &need_to_mix); |
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
142 } |
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
143 |
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
144 static void Mac_LockAudio(_THIS) |
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
145 { |
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
146 IncrementAtomic((SInt32 *) &audio_is_locked); |
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
147 } |
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
148 |
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
149 static void Mac_UnlockAudio(_THIS) |
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
150 { |
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
151 SInt32 oldval; |
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
152 |
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
153 oldval = DecrementAtomic((SInt32 *) &audio_is_locked); |
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
154 if ( oldval != 1 ) /* != 1 means audio is still locked. */ |
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
155 return; |
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
156 |
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
157 /* Did we miss the chance to mix in an interrupt? Do it now. */ |
324
f25f666d609a
*** empty log message ***
Sam Lantinga <slouken@libsdl.org>
parents:
323
diff
changeset
|
158 if ( BitAndAtomic (0xFFFFFFFF, (UInt32 *) &need_to_mix) ) { |
323
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
159 /* |
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
160 * Note that this could be a problem if you missed an interrupt |
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
161 * while the audio was locked, and get preempted by a second |
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
162 * interrupt here, but that means you locked for way too long anyhow. |
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
163 */ |
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
164 mix_buffer (this, buffer[fill_me]); |
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
165 } |
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
166 } |
0 | 167 |
168 static void callBackProc (SndChannel *chan, SndCommand *cmd_passed ) { | |
323
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
169 UInt32 play_me; |
0 | 170 SndCommand cmd; |
171 SDL_AudioDevice *audio = (SDL_AudioDevice *)chan->userInfo; | |
323
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
172 |
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
173 IncrementAtomic((SInt32 *) &need_to_mix); |
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
174 |
47
45b1c4303f87
Added initial support for Quartz video (thanks Darrell!)
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
175 fill_me = cmd_passed->param2; /* buffer that has just finished playing, so fill it */ |
0 | 176 play_me = ! fill_me; /* filled buffer to play _now_ */ |
177 | |
178 if ( ! audio->enabled ) { | |
179 return; | |
180 } | |
181 | |
323
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
182 /* queue previously mixed buffer for playback. */ |
0 | 183 header.samplePtr = (Ptr)buffer[play_me]; |
184 cmd.cmd = bufferCmd; | |
185 cmd.param1 = 0; | |
186 cmd.param2 = (long)&header; | |
323
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
187 SndDoCommand (chan, &cmd, 0); |
47
45b1c4303f87
Added initial support for Quartz video (thanks Darrell!)
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
188 |
0 | 189 memset (buffer[fill_me], 0, audio->spec.size); |
47
45b1c4303f87
Added initial support for Quartz video (thanks Darrell!)
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
190 |
323
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
191 /* |
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
192 * if audio device isn't locked, mix the next buffer to be queued in |
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
193 * the memory block that just finished playing. |
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
194 */ |
324
f25f666d609a
*** empty log message ***
Sam Lantinga <slouken@libsdl.org>
parents:
323
diff
changeset
|
195 if ( ! BitAndAtomic(0xFFFFFFFF, (UInt32 *) &audio_is_locked) ) { |
323
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
196 mix_buffer (audio, buffer[fill_me]); |
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
197 } |
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
198 |
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
199 /* set this callback to run again when current buffer drains. */ |
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
200 if ( running ) { |
0 | 201 cmd.cmd = callBackCmd; |
202 cmd.param1 = 0; | |
203 cmd.param2 = play_me; | |
204 | |
205 SndDoCommand (chan, &cmd, 0); | |
206 } | |
207 } | |
208 | |
209 static int Mac_OpenAudio(_THIS, SDL_AudioSpec *spec) { | |
210 | |
211 SndCallBackUPP callback; | |
212 int sample_bits; | |
213 int i; | |
214 long initOptions; | |
323
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
215 |
0 | 216 /* Very few conversions are required, but... */ |
217 switch (spec->format) { | |
218 case AUDIO_S8: | |
219 spec->format = AUDIO_U8; | |
220 break; | |
221 case AUDIO_U16LSB: | |
222 spec->format = AUDIO_S16LSB; | |
223 break; | |
224 case AUDIO_U16MSB: | |
225 spec->format = AUDIO_S16MSB; | |
226 break; | |
227 } | |
228 SDL_CalculateAudioSpec(spec); | |
229 | |
230 /* initialize bufferCmd header */ | |
231 memset (&header, 0, sizeof(header)); | |
232 callback = NewSndCallBackUPP (callBackProc); | |
233 sample_bits = spec->size / spec->samples / spec->channels * 8; | |
234 | |
235 #ifdef DEBUG_AUDIO | |
236 fprintf(stderr, | |
237 "Audio format 0x%x, channels = %d, sample_bits = %d, frequency = %d\n", | |
238 spec->format, spec->channels, sample_bits, spec->freq); | |
239 #endif /* DEBUG_AUDIO */ | |
240 | |
241 header.numChannels = spec->channels; | |
242 header.sampleSize = sample_bits; | |
243 header.sampleRate = spec->freq << 16; | |
244 header.numFrames = spec->samples; | |
245 header.encode = cmpSH; | |
246 | |
247 /* Note that we install the 16bitLittleEndian Converter if needed. */ | |
248 if ( spec->format == 0x8010 ) { | |
249 header.compressionID = fixedCompression; | |
250 header.format = k16BitLittleEndianFormat; | |
251 } | |
252 | |
253 /* allocate 2 buffers */ | |
254 for (i=0; i<2; i++) { | |
255 buffer[i] = (UInt8*)malloc (sizeof(UInt8) * spec->size); | |
256 if (buffer[i] == NULL) { | |
257 SDL_OutOfMemory(); | |
258 return (-1); | |
259 } | |
260 memset (buffer[i], 0, spec->size); | |
261 } | |
262 | |
263 /* Create the sound manager channel */ | |
264 channel = (SndChannelPtr)malloc(sizeof(*channel)); | |
265 if ( channel == NULL ) { | |
266 SDL_OutOfMemory(); | |
267 return(-1); | |
268 } | |
269 if ( spec->channels >= 2 ) { | |
270 initOptions = initStereo; | |
271 } else { | |
272 initOptions = initMono; | |
273 } | |
274 channel->userInfo = (long)this; | |
275 channel->qLength = 128; | |
323
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
276 if ( SndNewChannel(&channel, sampledSynth, initOptions, callback) != noErr ) { |
0 | 277 SDL_SetError("Unable to create audio channel"); |
278 free(channel); | |
279 channel = NULL; | |
280 return(-1); | |
281 } | |
282 | |
283 /* start playback */ | |
284 { | |
285 SndCommand cmd; | |
286 cmd.cmd = callBackCmd; | |
287 cmd.param2 = 0; | |
288 running = 1; | |
289 SndDoCommand (channel, &cmd, 0); | |
290 } | |
291 | |
292 return 1; | |
293 } | |
294 | |
295 static void Mac_CloseAudio(_THIS) { | |
296 | |
297 int i; | |
298 | |
299 running = 0; | |
300 | |
301 if (channel) { | |
302 SndDisposeChannel (channel, true); | |
303 channel = NULL; | |
304 } | |
305 | |
306 for ( i=0; i<2; ++i ) { | |
307 if ( buffer[i] ) { | |
308 free(buffer[i]); | |
309 buffer[i] = NULL; | |
310 } | |
311 } | |
312 } | |
313 | |
323
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
314 #else /* !TARGET_API_MAC_CARBON && !USE_RYANS_SOUNDCODE */ |
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
315 |
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
316 static void Mac_LockAudio(_THIS) |
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
317 { |
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
318 /* no-op. */ |
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
319 } |
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
320 |
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
321 static void Mac_UnlockAudio(_THIS) |
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
322 { |
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
323 /* no-op. */ |
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
324 } |
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
325 |
0 | 326 |
327 /* This function is called by Sound Manager when it has exhausted one of | |
328 the buffers, so we'll zero it to silence and fill it with audio if | |
329 we're not paused. | |
330 */ | |
331 static pascal | |
332 void sndDoubleBackProc (SndChannelPtr chan, SndDoubleBufferPtr newbuf) | |
333 { | |
334 SDL_AudioDevice *audio = (SDL_AudioDevice *)newbuf->dbUserInfo[0]; | |
335 | |
336 /* If audio is quitting, don't do anything */ | |
337 if ( ! audio->enabled ) { | |
338 return; | |
339 } | |
340 memset (newbuf->dbSoundData, 0, audio->spec.size); | |
341 newbuf->dbNumFrames = audio->spec.samples; | |
342 if ( ! audio->paused ) { | |
343 if ( audio->convert.needed ) { | |
344 audio->spec.callback(audio->spec.userdata, | |
345 (Uint8 *)audio->convert.buf,audio->convert.len); | |
346 SDL_ConvertAudio(&audio->convert); | |
347 #if 0 | |
348 if ( audio->convert.len_cvt != audio->spec.size ) { | |
349 /* Uh oh... probably crashes here */; | |
350 } | |
351 #endif | |
352 memcpy(newbuf->dbSoundData, audio->convert.buf, | |
353 audio->convert.len_cvt); | |
354 } else { | |
355 audio->spec.callback(audio->spec.userdata, | |
356 (Uint8 *)newbuf->dbSoundData, audio->spec.size); | |
357 } | |
358 } | |
359 newbuf->dbFlags |= dbBufferReady; | |
360 } | |
361 | |
362 static int DoubleBufferAudio_Available(void) | |
363 { | |
364 int available; | |
365 NumVersion sndversion; | |
366 long response; | |
367 | |
368 available = 0; | |
369 sndversion = SndSoundManagerVersion(); | |
370 if ( sndversion.majorRev >= 3 ) { | |
371 if ( Gestalt(gestaltSoundAttr, &response) == noErr ) { | |
372 if ( (response & (1 << gestaltSndPlayDoubleBuffer)) ) { | |
373 available = 1; | |
374 } | |
375 } | |
376 } else { | |
377 if ( Gestalt(gestaltSoundAttr, &response) == noErr ) { | |
378 if ( (response & (1 << gestaltHasASC)) ) { | |
379 available = 1; | |
380 } | |
381 } | |
382 } | |
383 return(available); | |
384 } | |
385 | |
386 static void Mac_CloseAudio(_THIS) | |
387 { | |
388 int i; | |
389 | |
390 if ( channel != NULL ) { | |
391 /* Clean up the audio channel */ | |
392 SndDisposeChannel(channel, true); | |
393 channel = NULL; | |
394 } | |
395 for ( i=0; i<2; ++i ) { | |
396 if ( audio_buf[i] ) { | |
397 free(audio_buf[i]); | |
398 audio_buf[i] = NULL; | |
399 } | |
400 } | |
401 } | |
402 | |
403 static int Mac_OpenAudio(_THIS, SDL_AudioSpec *spec) | |
404 { | |
405 SndDoubleBufferHeader2 audio_dbh; | |
406 int i; | |
407 long initOptions; | |
408 int sample_bits; | |
409 SndDoubleBackUPP doubleBackProc; | |
410 | |
411 /* Check to make sure double-buffered audio is available */ | |
412 if ( ! DoubleBufferAudio_Available() ) { | |
413 SDL_SetError("Sound manager doesn't support double-buffering"); | |
414 return(-1); | |
415 } | |
416 | |
417 /* Very few conversions are required, but... */ | |
418 switch (spec->format) { | |
419 case AUDIO_S8: | |
420 spec->format = AUDIO_U8; | |
421 break; | |
422 case AUDIO_U16LSB: | |
423 spec->format = AUDIO_S16LSB; | |
424 break; | |
425 case AUDIO_U16MSB: | |
426 spec->format = AUDIO_S16MSB; | |
427 break; | |
428 } | |
429 SDL_CalculateAudioSpec(spec); | |
430 | |
431 /* initialize the double-back header */ | |
432 memset(&audio_dbh, 0, sizeof(audio_dbh)); | |
433 doubleBackProc = NewSndDoubleBackProc (sndDoubleBackProc); | |
434 sample_bits = spec->size / spec->samples / spec->channels * 8; | |
435 | |
436 audio_dbh.dbhNumChannels = spec->channels; | |
437 audio_dbh.dbhSampleSize = sample_bits; | |
438 audio_dbh.dbhCompressionID = 0; | |
439 audio_dbh.dbhPacketSize = 0; | |
440 audio_dbh.dbhSampleRate = spec->freq << 16; | |
441 audio_dbh.dbhDoubleBack = doubleBackProc; | |
442 audio_dbh.dbhFormat = 0; | |
443 | |
444 /* Note that we install the 16bitLittleEndian Converter if needed. */ | |
445 if ( spec->format == 0x8010 ) { | |
446 audio_dbh.dbhCompressionID = fixedCompression; | |
447 audio_dbh.dbhFormat = k16BitLittleEndianFormat; | |
448 } | |
449 | |
450 /* allocate the 2 double-back buffers */ | |
451 for ( i=0; i<2; ++i ) { | |
452 audio_buf[i] = calloc(1, sizeof(SndDoubleBuffer)+spec->size); | |
453 if ( audio_buf[i] == NULL ) { | |
454 SDL_OutOfMemory(); | |
455 return(-1); | |
456 } | |
457 audio_buf[i]->dbNumFrames = spec->samples; | |
458 audio_buf[i]->dbFlags = dbBufferReady; | |
459 audio_buf[i]->dbUserInfo[0] = (long)this; | |
460 audio_dbh.dbhBufferPtr[i] = audio_buf[i]; | |
461 } | |
462 | |
463 /* Create the sound manager channel */ | |
464 channel = (SndChannelPtr)malloc(sizeof(*channel)); | |
465 if ( channel == NULL ) { | |
466 SDL_OutOfMemory(); | |
467 return(-1); | |
468 } | |
469 if ( spec->channels >= 2 ) { | |
470 initOptions = initStereo; | |
471 } else { | |
472 initOptions = initMono; | |
473 } | |
474 channel->userInfo = 0; | |
475 channel->qLength = 128; | |
476 if ( SndNewChannel(&channel, sampledSynth, initOptions, 0L) != noErr ) { | |
477 SDL_SetError("Unable to create audio channel"); | |
478 free(channel); | |
479 channel = NULL; | |
480 return(-1); | |
481 } | |
482 | |
483 /* Start playback */ | |
484 if ( SndPlayDoubleBuffer(channel, (SndDoubleBufferHeaderPtr)&audio_dbh) | |
485 != noErr ) { | |
486 SDL_SetError("Unable to play double buffered audio"); | |
487 return(-1); | |
488 } | |
489 | |
490 return 1; | |
491 } | |
492 | |
323
b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
493 #endif /* TARGET_API_MAC_CARBON || USE_RYANS_SOUNDCODE */ |
0 | 494 |