2
Simple DirectMedia Layer
3
Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
5
This software is provided 'as-is', without any express or implied
6
warranty. In no event will the authors be held liable for any damages
7
arising from the use of this software.
9
Permission is granted to anyone to use this software for any purpose,
10
including commercial applications, and to alter it and redistribute it
11
freely, subject to the following restrictions:
13
1. The origin of this software must not be misrepresented; you must not
14
claim that you wrote the original software. If you use this software
15
in a product, an acknowledgment in the product documentation would be
16
appreciated but is not required.
17
2. Altered source versions must be plainly marked as such, and must not be
18
misrepresented as being the original software.
19
3. This notice may not be removed or altered from any source distribution.
21
#include "SDL_config.h"
23
#if SDL_AUDIO_DRIVER_FUSIONSOUND
25
/* Allow access to a raw mixing buffer */
32
#include "SDL_timer.h"
33
#include "SDL_audio.h"
34
#include "../SDL_audiomem.h"
35
#include "../SDL_audio_c.h"
36
#include "SDL_fsaudio.h"
38
#include <fusionsound/fusionsound_version.h>
40
/* #define SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC "libfusionsound.so" */
42
#ifdef SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC
44
#include "SDL_loadso.h"
49
#if (FUSIONSOUND_MAJOR_VERSION == 1) && (FUSIONSOUND_MINOR_VERSION < 1)
50
typedef DFBResult DirectResult;
53
/* Buffers to use - more than 2 gives a lot of latency */
54
#define FUSION_BUFFERS (2)
56
#ifdef SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC
58
static const char *fs_library = SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC;
59
static void *fs_handle = NULL;
61
static DirectResult (*SDL_NAME(FusionSoundInit)) (int *argc, char *(*argv[]));
62
static DirectResult (*SDL_NAME(FusionSoundCreate)) (IFusionSound **
65
#define SDL_FS_SYM(x) { #x, (void **) (char *) &SDL_NAME(x) }
72
SDL_FS_SYM(FusionSoundInit),
73
SDL_FS_SYM(FusionSoundCreate),
80
UnloadFusionSoundLibrary()
82
if (fs_handle != NULL) {
83
SDL_UnloadObject(fs_handle);
89
LoadFusionSoundLibrary(void)
93
if (fs_handle == NULL) {
94
fs_handle = SDL_LoadObject(fs_library);
95
if (fs_handle != NULL) {
97
for (i = 0; i < SDL_arraysize(fs_functions); ++i) {
98
*fs_functions[i].func =
99
SDL_LoadFunction(fs_handle, fs_functions[i].name);
100
if (!*fs_functions[i].func) {
102
UnloadFusionSoundLibrary();
115
UnloadFusionSoundLibrary()
121
LoadFusionSoundLibrary(void)
126
#endif /* SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC */
128
/* This function waits until it is possible to write a full sound buffer */
130
SDL_FS_WaitDevice(_THIS)
132
this->hidden->stream->Wait(this->hidden->stream,
133
this->hidden->mixsamples);
137
SDL_FS_PlayDevice(_THIS)
141
ret = this->hidden->stream->Write(this->hidden->stream,
142
this->hidden->mixbuf,
143
this->hidden->mixsamples);
144
/* If we couldn't write, assume fatal error for now */
149
fprintf(stderr, "Wrote %d bytes of audio data\n", this->hidden->mixlen);
154
SDL_FS_WaitDone(_THIS)
156
this->hidden->stream->Wait(this->hidden->stream,
157
this->hidden->mixsamples * FUSION_BUFFERS);
162
SDL_FS_GetDeviceBuf(_THIS)
164
return (this->hidden->mixbuf);
169
SDL_FS_CloseDevice(_THIS)
171
if (this->hidden != NULL) {
172
SDL_FreeAudioMem(this->hidden->mixbuf);
173
this->hidden->mixbuf = NULL;
174
if (this->hidden->stream) {
175
this->hidden->stream->Release(this->hidden->stream);
176
this->hidden->stream = NULL;
178
if (this->hidden->fs) {
179
this->hidden->fs->Release(this->hidden->fs);
180
this->hidden->fs = NULL;
182
SDL_free(this->hidden);
189
SDL_FS_OpenDevice(_THIS, const char *devname, int iscapture)
192
SDL_AudioFormat test_format = 0, format = 0;
193
FSSampleFormat fs_format;
194
FSStreamDescription desc;
197
/* Initialize all variables that we clean on shutdown */
198
this->hidden = (struct SDL_PrivateAudioData *)
199
SDL_malloc((sizeof *this->hidden));
200
if (this->hidden == NULL) {
201
return SDL_OutOfMemory();
203
SDL_memset(this->hidden, 0, (sizeof *this->hidden));
205
/* Try for a closest match on audio format */
206
for (test_format = SDL_FirstAudioFormat(this->spec.format);
207
!format && test_format;) {
209
fprintf(stderr, "Trying format 0x%4.4x\n", test_format);
211
switch (test_format) {
218
fs_format = FSSF_S16;
223
fs_format = FSSF_S32;
228
fs_format = FSSF_FLOAT;
237
test_format = SDL_NextAudioFormat();
242
SDL_FS_CloseDevice(this);
243
return SDL_SetError("Couldn't find any hardware audio formats");
245
this->spec.format = test_format;
247
/* Retrieve the main sound interface. */
248
ret = SDL_NAME(FusionSoundCreate) (&this->hidden->fs);
250
SDL_FS_CloseDevice(this);
251
return SDL_SetError("Unable to initialize FusionSound: %d", ret);
254
this->hidden->mixsamples = this->spec.size / bytes / this->spec.channels;
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;
263
desc.sampleformat = fs_format;
266
this->hidden->fs->CreateStream(this->hidden->fs, &desc,
267
&this->hidden->stream);
269
SDL_FS_CloseDevice(this);
270
return SDL_SetError("Unable to create FusionSoundStream: %d", ret);
273
/* See what we got */
274
desc.flags = FSSDF_SAMPLERATE | FSSDF_BUFFERSIZE |
275
FSSDF_CHANNELS | FSSDF_SAMPLEFORMAT;
276
ret = this->hidden->stream->GetDescription(this->hidden->stream, &desc);
278
this->spec.freq = desc.samplerate;
280
desc.buffersize / FUSION_BUFFERS * bytes * desc.channels;
281
this->spec.channels = desc.channels;
283
/* Calculate the final parameters for this audio specification */
284
SDL_CalculateAudioSpec(&this->spec);
286
/* Allocate mixing buffer */
287
this->hidden->mixlen = this->spec.size;
288
this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
289
if (this->hidden->mixbuf == NULL) {
290
SDL_FS_CloseDevice(this);
291
return SDL_OutOfMemory();
293
SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
295
/* We're ready to rock and roll. :-) */
301
SDL_FS_Deinitialize(void)
303
UnloadFusionSoundLibrary();
308
SDL_FS_Init(SDL_AudioDriverImpl * impl)
310
if (LoadFusionSoundLibrary() < 0) {
315
ret = SDL_NAME(FusionSoundInit) (NULL, NULL);
317
UnloadFusionSoundLibrary();
319
("FusionSound: SDL_FS_init failed (FusionSoundInit: %d)",
325
/* Set the function pointers */
326
impl->OpenDevice = SDL_FS_OpenDevice;
327
impl->PlayDevice = SDL_FS_PlayDevice;
328
impl->WaitDevice = SDL_FS_WaitDevice;
329
impl->GetDeviceBuf = SDL_FS_GetDeviceBuf;
330
impl->CloseDevice = SDL_FS_CloseDevice;
331
impl->WaitDone = SDL_FS_WaitDone;
332
impl->Deinitialize = SDL_FS_Deinitialize;
333
impl->OnlyHasDefaultOutputDevice = 1;
335
return 1; /* this audio target is available. */
339
AudioBootStrap FUSIONSOUND_bootstrap = {
340
"fusionsound", "FusionSound", SDL_FS_Init, 0
343
#endif /* SDL_AUDIO_DRIVER_FUSIONSOUND */
345
/* vi: set ts=4 sw=4 expandtab: */