2 Simple DirectMedia Layer
3 Copyright (C) 1997-2018 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_internal.h"
23 #if SDL_AUDIO_DRIVER_FUSIONSOUND
25 /* !!! FIXME: why is this is SDL_FS_* instead of FUSIONSOUND_*? */
27 /* Allow access to a raw mixing buffer */
34 #include "SDL_timer.h"
35 #include "SDL_audio.h"
36 #include "../SDL_audio_c.h"
37 #include "SDL_fsaudio.h"
39 #include <fusionsound/fusionsound_version.h>
41 /* #define SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC "libfusionsound.so" */
43 #ifdef SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC
45 #include "SDL_loadso.h"
50 #if (FUSIONSOUND_MAJOR_VERSION == 1) && (FUSIONSOUND_MINOR_VERSION < 1)
51 typedef DFBResult DirectResult;
54 /* Buffers to use - more than 2 gives a lot of latency */
55 #define FUSION_BUFFERS (2)
57 #ifdef SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC
59 static const char *fs_library = SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC;
60 static void *fs_handle = NULL;
62 static DirectResult (*SDL_NAME(FusionSoundInit)) (int *argc, char *(*argv[]));
63 static DirectResult (*SDL_NAME(FusionSoundCreate)) (IFusionSound **
66 #define SDL_FS_SYM(x) { #x, (void **) (char *) &SDL_NAME(x) }
73 SDL_FS_SYM(FusionSoundInit),
74 SDL_FS_SYM(FusionSoundCreate),
81 UnloadFusionSoundLibrary()
83 if (fs_handle != NULL) {
84 SDL_UnloadObject(fs_handle);
90 LoadFusionSoundLibrary(void)
94 if (fs_handle == NULL) {
95 fs_handle = SDL_LoadObject(fs_library);
96 if (fs_handle != NULL) {
98 for (i = 0; i < SDL_arraysize(fs_functions); ++i) {
99 *fs_functions[i].func =
100 SDL_LoadFunction(fs_handle, fs_functions[i].name);
101 if (!*fs_functions[i].func) {
103 UnloadFusionSoundLibrary();
116 UnloadFusionSoundLibrary()
122 LoadFusionSoundLibrary(void)
127 #endif /* SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC */
129 /* This function waits until it is possible to write a full sound buffer */
131 SDL_FS_WaitDevice(_THIS)
133 this->hidden->stream->Wait(this->hidden->stream,
134 this->hidden->mixsamples);
138 SDL_FS_PlayDevice(_THIS)
142 ret = this->hidden->stream->Write(this->hidden->stream,
143 this->hidden->mixbuf,
144 this->hidden->mixsamples);
145 /* If we couldn't write, assume fatal error for now */
147 SDL_OpenedAudioDeviceDisconnected(this);
150 fprintf(stderr, "Wrote %d bytes of audio data\n", this->hidden->mixlen);
156 SDL_FS_GetDeviceBuf(_THIS)
158 return (this->hidden->mixbuf);
163 SDL_FS_CloseDevice(_THIS)
165 if (this->hidden->stream) {
166 this->hidden->stream->Release(this->hidden->stream);
168 if (this->hidden->fs) {
169 this->hidden->fs->Release(this->hidden->fs);
171 SDL_free(this->hidden->mixbuf);
172 SDL_free(this->hidden);
177 SDL_FS_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
180 SDL_AudioFormat test_format = 0, format = 0;
181 FSSampleFormat fs_format;
182 FSStreamDescription desc;
185 /* Initialize all variables that we clean on shutdown */
186 this->hidden = (struct SDL_PrivateAudioData *)
187 SDL_malloc((sizeof *this->hidden));
188 if (this->hidden == NULL) {
189 return SDL_OutOfMemory();
191 SDL_zerop(this->hidden);
193 /* Try for a closest match on audio format */
194 for (test_format = SDL_FirstAudioFormat(this->spec.format);
195 !format && test_format;) {
197 fprintf(stderr, "Trying format 0x%4.4x\n", test_format);
199 switch (test_format) {
206 fs_format = FSSF_S16;
211 fs_format = FSSF_S32;
216 fs_format = FSSF_FLOAT;
225 test_format = SDL_NextAudioFormat();
230 return SDL_SetError("Couldn't find any hardware audio formats");
232 this->spec.format = test_format;
234 /* Retrieve the main sound interface. */
235 ret = SDL_NAME(FusionSoundCreate) (&this->hidden->fs);
237 return SDL_SetError("Unable to initialize FusionSound: %d", ret);
240 this->hidden->mixsamples = this->spec.size / bytes / this->spec.channels;
242 /* Fill stream description. */
243 desc.flags = FSSDF_SAMPLERATE | FSSDF_BUFFERSIZE |
244 FSSDF_CHANNELS | FSSDF_SAMPLEFORMAT | FSSDF_PREBUFFER;
245 desc.samplerate = this->spec.freq;
246 desc.buffersize = this->spec.size * FUSION_BUFFERS;
247 desc.channels = this->spec.channels;
249 desc.sampleformat = fs_format;
252 this->hidden->fs->CreateStream(this->hidden->fs, &desc,
253 &this->hidden->stream);
255 return SDL_SetError("Unable to create FusionSoundStream: %d", ret);
258 /* See what we got */
259 desc.flags = FSSDF_SAMPLERATE | FSSDF_BUFFERSIZE |
260 FSSDF_CHANNELS | FSSDF_SAMPLEFORMAT;
261 ret = this->hidden->stream->GetDescription(this->hidden->stream, &desc);
263 this->spec.freq = desc.samplerate;
265 desc.buffersize / FUSION_BUFFERS * bytes * desc.channels;
266 this->spec.channels = desc.channels;
268 /* Calculate the final parameters for this audio specification */
269 SDL_CalculateAudioSpec(&this->spec);
271 /* Allocate mixing buffer */
272 this->hidden->mixlen = this->spec.size;
273 this->hidden->mixbuf = (Uint8 *) SDL_malloc(this->hidden->mixlen);
274 if (this->hidden->mixbuf == NULL) {
275 return SDL_OutOfMemory();
277 SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
279 /* We're ready to rock and roll. :-) */
285 SDL_FS_Deinitialize(void)
287 UnloadFusionSoundLibrary();
292 SDL_FS_Init(SDL_AudioDriverImpl * impl)
294 if (LoadFusionSoundLibrary() < 0) {
299 ret = SDL_NAME(FusionSoundInit) (NULL, NULL);
301 UnloadFusionSoundLibrary();
303 ("FusionSound: SDL_FS_init failed (FusionSoundInit: %d)",
309 /* Set the function pointers */
310 impl->OpenDevice = SDL_FS_OpenDevice;
311 impl->PlayDevice = SDL_FS_PlayDevice;
312 impl->WaitDevice = SDL_FS_WaitDevice;
313 impl->GetDeviceBuf = SDL_FS_GetDeviceBuf;
314 impl->CloseDevice = SDL_FS_CloseDevice;
315 impl->Deinitialize = SDL_FS_Deinitialize;
316 impl->OnlyHasDefaultOutputDevice = 1;
318 return 1; /* this audio target is available. */
322 AudioBootStrap FUSIONSOUND_bootstrap = {
323 "fusionsound", "FusionSound", SDL_FS_Init, 0
326 #endif /* SDL_AUDIO_DRIVER_FUSIONSOUND */
328 /* vi: set ts=4 sw=4 expandtab: */