comparison src/audio/fusionsound/SDL_fsaudio.c @ 2947:fec0db6c44b7

Date: Thu, 01 Jan 2009 21:32:12 +0100 From: Couriersud Subject: Fusionsound audio driver attached is a diff containing a audio driver for the FusionSound library. This sound library is closely related to DirectFB and uses the same transport (fusion) as DirectFB when running applications "remote", i.e. over the network. As such, it natively redirects sound where DirectFB redirects video. This may be handy for everyone using SDL over DirectFB.
author Sam Lantinga <slouken@libsdl.org>
date Thu, 01 Jan 2009 21:34:22 +0000
parents
children 816a7a65a59a
comparison
equal deleted inserted replaced
2946:29e1f863a844 2947:fec0db6c44b7
1 /*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2009 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 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 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 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 /* Allow access to a raw mixing buffer */
25
26 #ifdef HAVE_SIGNAL_H
27 #include <signal.h>
28 #endif
29 #include <unistd.h>
30
31 #include "SDL_timer.h"
32 #include "SDL_audio.h"
33 #include "../SDL_audiomem.h"
34 #include "../SDL_audio_c.h"
35 #include "SDL_fsaudio.h"
36
37 //#define SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC "libfusionsound.so"
38
39 #ifdef SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC
40 #include "SDL_name.h"
41 #include "SDL_loadso.h"
42 #else
43 #define SDL_NAME(X) X
44 #endif
45
46 /* The tag name used by fusionsoundc audio */
47 #define SDL_FS_DRIVER_NAME "fusionsound"
48 /* Buffers to use - more than 2 gives a lot of latency */
49 #define FUSION_BUFFERS (2)
50
51 #ifdef SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC
52
53 static const char *fs_library = SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC;
54 static void *fs_handle = NULL;
55
56 static DirectResult(*SDL_NAME(FusionSoundInit)) (int *argc, char *(*argv[]));
57 static DirectResult(*SDL_NAME(FusionSoundCreate)) (IFusionSound **
58 ret_interface);
59
60 #define SDL_FS_SYM(x) { #x, (void **) (char *) &SDL_NAME(x) }
61 static struct
62 {
63 const char *name;
64 void **func;
65 } fs_functions[] = {
66 /* *INDENT-OFF* */
67 SDL_FS_SYM(FusionSoundInit),
68 SDL_FS_SYM(FusionSoundCreate),
69 /* *INDENT-ON* */
70 };
71
72 #undef SDL_FS_SYM
73
74 static void
75 UnloadFusionSoundLibrary()
76 {
77 if (fs_handle != NULL) {
78 SDL_UnloadObject(fs_handle);
79 fs_handle = NULL;
80 }
81 }
82
83 static int
84 LoadFusionSoundLibrary(void)
85 {
86 int i, retval = -1;
87
88 if (fs_handle == NULL) {
89 fs_handle = SDL_LoadObject(fs_library);
90 if (fs_handle != NULL) {
91 retval = 0;
92 for (i = 0; i < SDL_arraysize(fs_functions); ++i) {
93 *fs_functions[i].func =
94 SDL_LoadFunction(fs_handle, fs_functions[i].name);
95 if (!*fs_functions[i].func) {
96 retval = -1;
97 UnloadFusionSoundLibrary();
98 break;
99 }
100 }
101 }
102 }
103
104 return retval;
105 }
106
107 #else
108
109 static void
110 UnloadFusionSoundLibrary()
111 {
112 return;
113 }
114
115 static int
116 LoadFusionSoundLibrary(void)
117 {
118 return 0;
119 }
120
121 #endif /* SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC */
122
123 /* This function waits until it is possible to write a full sound buffer */
124 static void
125 SDL_FS_WaitDevice(_THIS)
126 {
127 this->hidden->stream->Wait(this->hidden->stream,
128 this->hidden->mixsamples);
129 }
130
131 static void
132 SDL_FS_PlayDevice(_THIS)
133 {
134 DirectResult ret;
135
136 ret = this->hidden->stream->Write(this->hidden->stream,
137 this->hidden->mixbuf,
138 this->hidden->mixsamples);
139 /* If we couldn't write, assume fatal error for now */
140 if (ret) {
141 this->enabled = 0;
142 }
143 #ifdef DEBUG_AUDIO
144 fprintf(stderr, "Wrote %d bytes of audio data\n", this->hidden->mixlen);
145 #endif
146 }
147
148 static void
149 SDL_FS_WaitDone(_THIS)
150 {
151 this->hidden->stream->Wait(this->hidden->stream,
152 this->hidden->mixsamples * FUSION_BUFFERS);
153 }
154
155
156 static Uint8 *
157 SDL_FS_GetDeviceBuf(_THIS)
158 {
159 return (this->hidden->mixbuf);
160 }
161
162
163 static void
164 SDL_FS_CloseDevice(_THIS)
165 {
166 if (this->hidden != NULL) {
167 if (this->hidden->mixbuf != NULL) {
168 SDL_FreeAudioMem(this->hidden->mixbuf);
169 this->hidden->mixbuf = NULL;
170 }
171 if (this->hidden->stream) {
172 this->hidden->stream->Release(this->hidden->stream);
173 this->hidden->stream = NULL;
174 }
175 if (this->hidden->fs) {
176 this->hidden->fs->Release(this->hidden->fs);
177 this->hidden->fs = NULL;
178 }
179 SDL_free(this->hidden);
180 this->hidden = NULL;
181 }
182 }
183
184
185 static int
186 SDL_FS_OpenDevice(_THIS, const char *devname, int iscapture)
187 {
188 int bytes;
189 SDL_AudioFormat test_format = 0, format = 0;
190 FSSampleFormat fs_format;
191 FSStreamDescription desc;
192 DirectResult ret;
193
194 /* Initialize all variables that we clean on shutdown */
195 this->hidden = (struct SDL_PrivateAudioData *)
196 SDL_malloc((sizeof *this->hidden));
197 if (this->hidden == NULL) {
198 SDL_OutOfMemory();
199 return 0;
200 }
201 SDL_memset(this->hidden, 0, (sizeof *this->hidden));
202
203 /* Try for a closest match on audio format */
204 for (test_format = SDL_FirstAudioFormat(this->spec.format);
205 !format && test_format;) {
206 #ifdef DEBUG_AUDIO
207 fprintf(stderr, "Trying format 0x%4.4x\n", test_format);
208 #endif
209 switch (test_format) {
210 case AUDIO_U8:
211 fs_format = FSSF_U8;
212 bytes = 1;
213 format = 1;
214 break;
215 case AUDIO_S16SYS:
216 fs_format = FSSF_S16;
217 bytes = 2;
218 format = 1;
219 break;
220 case AUDIO_S32SYS:
221 fs_format = FSSF_S32;
222 bytes = 4;
223 format = 1;
224 break;
225 case AUDIO_F32SYS:
226 fs_format = FSSF_FLOAT;
227 bytes = 4;
228 format = 1;
229 break;
230 default:
231 format = 0;
232 break;
233 }
234 if (!format) {
235 test_format = SDL_NextAudioFormat();
236 }
237 }
238
239 if (format == 0) {
240 SDL_FS_CloseDevice(this);
241 SDL_SetError("Couldn't find any hardware audio formats");
242 return 0;
243 }
244 this->spec.format = test_format;
245
246 /* Retrieve the main sound interface. */
247 ret = SDL_NAME(FusionSoundCreate) (&this->hidden->fs);
248 if (ret) {
249 SDL_FS_CloseDevice(this);
250 SDL_SetError("Unable to initialize FusionSound: %d", ret);
251 return 0;
252 }
253
254 this->hidden->mixsamples = this->spec.size / bytes / this->spec.channels;
255
256 /* Fill stream description. */
257 desc.flags = FSSDF_SAMPLERATE | FSSDF_BUFFERSIZE |
258 FSSDF_CHANNELS | FSSDF_SAMPLEFORMAT | FSSDF_PREBUFFER;
259 desc.samplerate = this->spec.freq;
260 desc.buffersize = this->spec.size * FUSION_BUFFERS;
261 desc.channels = this->spec.channels;
262 desc.prebuffer = 10;
263 desc.sampleformat = fs_format;
264
265 ret =
266 this->hidden->fs->CreateStream(this->hidden->fs, &desc,
267 &this->hidden->stream);
268 if (ret) {
269 SDL_FS_CloseDevice(this);
270 SDL_SetError("Unable to create FusionSoundStream: %d", ret);
271 return 0;
272 }
273
274 /* See what we got */
275 desc.flags = FSSDF_SAMPLERATE | FSSDF_BUFFERSIZE |
276 FSSDF_CHANNELS | FSSDF_SAMPLEFORMAT;
277 ret = this->hidden->stream->GetDescription(this->hidden->stream, &desc);
278
279 this->spec.freq = desc.samplerate;
280 this->spec.size =
281 desc.buffersize / FUSION_BUFFERS * bytes * desc.channels;
282 this->spec.channels = desc.channels;
283
284 /* Calculate the final parameters for this audio specification */
285 SDL_CalculateAudioSpec(&this->spec);
286
287 /* Allocate mixing buffer */
288 this->hidden->mixlen = this->spec.size;
289 this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
290 if (this->hidden->mixbuf == NULL) {
291 SDL_FS_CloseDevice(this);
292 SDL_OutOfMemory();
293 return 0;
294 }
295 SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
296
297 /* We're ready to rock and roll. :-) */
298 return 1;
299 }
300
301
302 static void
303 SDL_FS_Deinitialize(void)
304 {
305 UnloadFusionSoundLibrary();
306 }
307
308
309 static int
310 SDL_FS_Init(SDL_AudioDriverImpl * impl)
311 {
312 if (LoadFusionSoundLibrary() < 0) {
313 return 0;
314 } else {
315 DirectResult ret;
316
317 ret = SDL_NAME(FusionSoundInit) (NULL, NULL);
318 if (ret) {
319 UnloadFusionSoundLibrary();
320 SDL_SetError
321 ("FusionSound: SDL_FS_init failed (FusionSoundInit: %d)",
322 ret);
323 return 0;
324 }
325 }
326
327 /* Set the function pointers */
328 impl->OpenDevice = SDL_FS_OpenDevice;
329 impl->PlayDevice = SDL_FS_PlayDevice;
330 impl->WaitDevice = SDL_FS_WaitDevice;
331 impl->GetDeviceBuf = SDL_FS_GetDeviceBuf;
332 impl->CloseDevice = SDL_FS_CloseDevice;
333 impl->WaitDone = SDL_FS_WaitDone;
334 impl->Deinitialize = SDL_FS_Deinitialize;
335 impl->OnlyHasDefaultOutputDevice = 1;
336
337 return 1;
338 }
339
340
341 AudioBootStrap FUSIONSOUND_bootstrap = {
342 SDL_FS_DRIVER_NAME, "FusionSound", SDL_FS_Init, 0
343 };
344
345 /* vi: set ts=4 sw=4 expandtab: */