SDL 2.0
SDL_fsaudio.c
Go to the documentation of this file.
1/*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2019 Sam Lantinga <slouken@libsdl.org>
4
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.
8
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:
12
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.
20*/
21#include "../../SDL_internal.h"
22
23#if SDL_AUDIO_DRIVER_FUSIONSOUND
24
25/* !!! FIXME: why is this is SDL_FS_* instead of FUSIONSOUND_*? */
26
27/* Allow access to a raw mixing buffer */
28
29#ifdef HAVE_SIGNAL_H
30#include <signal.h>
31#endif
32#include <unistd.h>
33
34#include "SDL_timer.h"
35#include "SDL_audio.h"
36#include "../SDL_audio_c.h"
37#include "SDL_fsaudio.h"
38
39#include <fusionsound/fusionsound_version.h>
40
41/* #define SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC "libfusionsound.so" */
42
43#ifdef SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC
44#include "SDL_name.h"
45#include "SDL_loadso.h"
46#else
47#define SDL_NAME(X) X
48#endif
49
50#if (FUSIONSOUND_MAJOR_VERSION == 1) && (FUSIONSOUND_MINOR_VERSION < 1)
51typedef DFBResult DirectResult;
52#endif
53
54/* Buffers to use - more than 2 gives a lot of latency */
55#define FUSION_BUFFERS (2)
56
57#ifdef SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC
58
59static const char *fs_library = SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC;
60static void *fs_handle = NULL;
61
62static DirectResult (*SDL_NAME(FusionSoundInit)) (int *argc, char *(*argv[]));
63static DirectResult (*SDL_NAME(FusionSoundCreate)) (IFusionSound **
64 ret_interface);
65
66#define SDL_FS_SYM(x) { #x, (void **) (char *) &SDL_NAME(x) }
67static struct
68{
69 const char *name;
70 void **func;
71} fs_functions[] = {
72/* *INDENT-OFF* */
73 SDL_FS_SYM(FusionSoundInit),
74 SDL_FS_SYM(FusionSoundCreate),
75/* *INDENT-ON* */
76};
77
78#undef SDL_FS_SYM
79
80static void
81UnloadFusionSoundLibrary()
82{
83 if (fs_handle != NULL) {
84 SDL_UnloadObject(fs_handle);
85 fs_handle = NULL;
86 }
87}
88
89static int
90LoadFusionSoundLibrary(void)
91{
92 int i, retval = -1;
93
94 if (fs_handle == NULL) {
95 fs_handle = SDL_LoadObject(fs_library);
96 if (fs_handle != NULL) {
97 retval = 0;
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) {
102 retval = -1;
103 UnloadFusionSoundLibrary();
104 break;
105 }
106 }
107 }
108 }
109
110 return retval;
111}
112
113#else
114
115static void
116UnloadFusionSoundLibrary()
117{
118 return;
119}
120
121static int
122LoadFusionSoundLibrary(void)
123{
124 return 0;
125}
126
127#endif /* SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC */
128
129/* This function waits until it is possible to write a full sound buffer */
130static void
131SDL_FS_WaitDevice(_THIS)
132{
133 this->hidden->stream->Wait(this->hidden->stream,
134 this->hidden->mixsamples);
135}
136
137static void
138SDL_FS_PlayDevice(_THIS)
139{
140 DirectResult ret;
141
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 */
146 if (ret) {
148 }
149#ifdef DEBUG_AUDIO
150 fprintf(stderr, "Wrote %d bytes of audio data\n", this->hidden->mixlen);
151#endif
152}
153
154
155static Uint8 *
156SDL_FS_GetDeviceBuf(_THIS)
157{
158 return (this->hidden->mixbuf);
159}
160
161
162static void
163SDL_FS_CloseDevice(_THIS)
164{
165 if (this->hidden->stream) {
166 this->hidden->stream->Release(this->hidden->stream);
167 }
168 if (this->hidden->fs) {
169 this->hidden->fs->Release(this->hidden->fs);
170 }
171 SDL_free(this->hidden->mixbuf);
172 SDL_free(this->hidden);
173}
174
175
176static int
177SDL_FS_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
178{
179 int bytes;
180 SDL_AudioFormat test_format = 0, format = 0;
181 FSSampleFormat fs_format;
182 FSStreamDescription desc;
183 DirectResult ret;
184
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();
190 }
191 SDL_zerop(this->hidden);
192
193 /* Try for a closest match on audio format */
194 for (test_format = SDL_FirstAudioFormat(this->spec.format);
195 !format && test_format;) {
196#ifdef DEBUG_AUDIO
197 fprintf(stderr, "Trying format 0x%4.4x\n", test_format);
198#endif
199 switch (test_format) {
200 case AUDIO_U8:
201 fs_format = FSSF_U8;
202 bytes = 1;
203 format = 1;
204 break;
205 case AUDIO_S16SYS:
206 fs_format = FSSF_S16;
207 bytes = 2;
208 format = 1;
209 break;
210 case AUDIO_S32SYS:
211 fs_format = FSSF_S32;
212 bytes = 4;
213 format = 1;
214 break;
215 case AUDIO_F32SYS:
216 fs_format = FSSF_FLOAT;
217 bytes = 4;
218 format = 1;
219 break;
220 default:
221 format = 0;
222 break;
223 }
224 if (!format) {
225 test_format = SDL_NextAudioFormat();
226 }
227 }
228
229 if (format == 0) {
230 return SDL_SetError("Couldn't find any hardware audio formats");
231 }
232 this->spec.format = test_format;
233
234 /* Retrieve the main sound interface. */
235 ret = SDL_NAME(FusionSoundCreate) (&this->hidden->fs);
236 if (ret) {
237 return SDL_SetError("Unable to initialize FusionSound: %d", ret);
238 }
239
240 this->hidden->mixsamples = this->spec.size / bytes / this->spec.channels;
241
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;
248 desc.prebuffer = 10;
249 desc.sampleformat = fs_format;
250
251 ret =
252 this->hidden->fs->CreateStream(this->hidden->fs, &desc,
253 &this->hidden->stream);
254 if (ret) {
255 return SDL_SetError("Unable to create FusionSoundStream: %d", ret);
256 }
257
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);
262
263 this->spec.freq = desc.samplerate;
264 this->spec.size =
265 desc.buffersize / FUSION_BUFFERS * bytes * desc.channels;
266 this->spec.channels = desc.channels;
267
268 /* Calculate the final parameters for this audio specification */
270
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();
276 }
277 SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
278
279 /* We're ready to rock and roll. :-) */
280 return 0;
281}
282
283
284static void
285SDL_FS_Deinitialize(void)
286{
287 UnloadFusionSoundLibrary();
288}
289
290
291static int
292SDL_FS_Init(SDL_AudioDriverImpl * impl)
293{
294 if (LoadFusionSoundLibrary() < 0) {
295 return 0;
296 } else {
297 DirectResult ret;
298
299 ret = SDL_NAME(FusionSoundInit) (NULL, NULL);
300 if (ret) {
301 UnloadFusionSoundLibrary();
303 ("FusionSound: SDL_FS_init failed (FusionSoundInit: %d)",
304 ret);
305 return 0;
306 }
307 }
308
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;
317
318 return 1; /* this audio target is available. */
319}
320
321
323 "fusionsound", "FusionSound", SDL_FS_Init, 0
324};
325
326#endif /* SDL_AUDIO_DRIVER_FUSIONSOUND */
327
328/* vi: set ts=4 sw=4 expandtab: */
#define _THIS
void SDL_CalculateAudioSpec(SDL_AudioSpec *spec)
Definition: SDL_audio.c:1668
SDL_AudioFormat SDL_FirstAudioFormat(SDL_AudioFormat format)
Definition: SDL_audio.c:1647
void SDL_OpenedAudioDeviceDisconnected(SDL_AudioDevice *device)
Definition: SDL_audio.c:486
SDL_AudioFormat SDL_NextAudioFormat(void)
Definition: SDL_audio.c:1659
#define AUDIO_S16SYS
Definition: SDL_audio.h:123
Uint16 SDL_AudioFormat
Audio format flags.
Definition: SDL_audio.h:64
#define AUDIO_U8
Definition: SDL_audio.h:89
#define AUDIO_S32SYS
Definition: SDL_audio.h:124
#define AUDIO_F32SYS
Definition: SDL_audio.h:125
#define SDL_SetError
#define SDL_memset
#define SDL_LoadObject
#define SDL_UnloadObject
#define SDL_malloc
#define SDL_free
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
void * SDL_LoadFunction(void *handle, const char *name)
#define SDL_NAME(X)
Definition: SDL_name.h:29
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: SDL_opengl.h:1572
GLenum func
GLuint const GLchar * name
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:115
#define SDL_zerop(x)
Definition: SDL_stdinc.h:417
uint8_t Uint8
Definition: SDL_stdinc.h:179
AudioBootStrap FUSIONSOUND_bootstrap
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
Definition: SDL_x11sym.h:50
#define NULL
Definition: begin_code.h:167
EGLImageKHR EGLint EGLint * handle
Definition: eglext.h:937
SDL_AudioSpec spec
Definition: loopwave.c:31
void(* PlayDevice)(_THIS)
Definition: SDL_sysaudio.h:73
void(* WaitDevice)(_THIS)
Definition: SDL_sysaudio.h:72
void(* CloseDevice)(_THIS)
Definition: SDL_sysaudio.h:78
void(* Deinitialize)(void)
Definition: SDL_sysaudio.h:82
int(* OpenDevice)(_THIS, void *handle, const char *devname, int iscapture)
Definition: SDL_sysaudio.h:68
Uint8 *(* GetDeviceBuf)(_THIS)
Definition: SDL_sysaudio.h:74
Uint32 size
Definition: SDL_audio.h:186
Uint8 channels
Definition: SDL_audio.h:182
SDL_AudioFormat format
Definition: SDL_audio.h:181
SDL_bool retval