1 /*
2  *  SPDX-License-Identifier: GPL-2.0-or-later
3  *
4  *  Copyright (C) 2020-2021  The DOSBox Staging Team
5  *  Copyright (C) 2018-2021  kcgen <kcgen@users.noreply.github.com>
6  *  Copyright (C) 2001-2017  Ryan C. Gordon <icculus@icculus.org>
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License along
19  *  with this program; if not, write to the Free Software Foundation, Inc.,
20  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21  */
22 
23 /*
24  *  Modified SDL Sound API implementation
25  *  -------------------------------------
26  *  Internal function/structure declaration. Do NOT include in your
27  *  application.
28  */
29 
30 #ifndef _INCLUDE_SDL_SOUND_INTERNAL_H_
31 #define _INCLUDE_SDL_SOUND_INTERNAL_H_
32 
33 #ifndef __SDL_SOUND_INTERNAL__
34 #error Do not include this header from your applications.
35 #endif
36 
37 #include <SDL.h>
38 
39 /* SDL 1.2.4 defines this, but better safe than sorry. */
40 #if (!defined(__inline__))
41 #  define __inline__
42 #endif
43 
44 #if (defined DEBUG_CHATTER)
45 #define SNDDBG(x) printf x
46 #else
47 #define SNDDBG(x)
48 #endif
49 
50 #if HAVE_ASSERT_H
51 #  include <assert.h>
52 #endif
53 
54 #ifdef _WIN32_WCE
55     extern char *strrchr(const char *s, int c);
56 #   ifdef NDEBUG
57 #       define assert(x)
58 #   else
59 #       define assert(x) if(!x) { fprintf(stderr,"Assertion failed in %s, line %s.\n",__FILE__,__LINE__); fclose(stderr); fclose(stdout); exit(1); }
60 #   endif
61 #endif
62 
63 
64 #if (!defined assert)  /* if all else fails. */
65 #  define assert(x)
66 #endif
67 
68 
69 /*
70  * SDL itself only supports mono and stereo output, but hopefully we can
71  *  raise this value someday...there's probably a lot of assumptions in
72  *  SDL_sound that rely on it, though.
73  */
74 #define MAX_CHANNELS 2
75 
76 
77 typedef struct __SOUND_DECODERFUNCTIONS__
78 {
79         /* This is a block of info about your decoder. See SDL_sound.h. */
80     const Sound_DecoderInfo info;
81 
82         /*
83          * This is called during the Sound_Init() function. Use this to
84          *  set up any global state that your decoder needs, such as
85          *  initializing an external library, etc.
86          *
87          * Return non-zero if initialization is successful, zero if there's
88          *  a fatal error. If this method fails, then this decoder is
89          *  flagged as unavailable until SDL_sound() is shut down and
90          *  reinitialized, in which case this method will be tried again.
91          *
92          * Note that the decoders quit() method won't be called if this
93          *  method fails, so if you can't intialize, you'll have to clean
94          *  up the half-initialized state in this method.
95          */
96     int (*init)(void);
97 
98         /*
99          * This is called during the Sound_Quit() function. Use this to
100          *  clean up any global state that your decoder has used during its
101          *  lifespan.
102          */
103     void (*quit)(void);
104 
105         /*
106          * Returns non-zero if (sample) has a valid fileformat that this
107          *  driver can handle. Zero if this driver can NOT handle the data.
108          *
109          * Extension, which may be NULL, is just a hint as to the form of
110          *  data that is being passed in. Most decoders should determine if
111          *  they can handle the data by the data itself, but others, like
112          *  the raw data handler, need this hint to know if they should
113          *  accept the data in the first place.
114          *
115          * (sample)'s (opaque) field should be cast to a Sound_SampleInternal
116          *  pointer:
117          *
118          *   Sound_SampleInternal *internal;
119          *   internal = (Sound_SampleInternal *) sample->opaque;
120          *
121          * Certain fields of sample will be filled in for the decoder before
122          *  this call, and others should be filled in by the decoder. Some
123          *  fields are offlimits, and should NOT be modified. The list:
124          *
125          * in Sound_SampleInternal section:
126          *    Sound_Sample *next;  (offlimits)
127          *    Sound_Sample *prev;  (offlimits)
128          *    SDL_RWops *rw;       (can use, but do NOT close it)
129          *    const Sound_DecoderFunctions *funcs; (that's this structure)
130          *    void *decoder_private; (read and write access)
131          *
132          * in rest of Sound_Sample:
133          *    void *opaque;        (this was internal section, above)
134          *    const Sound_DecoderInfo *decoder;  (read only)
135          *    Sound_AudioInfo desired; (read only, usually not needed here)
136          *    Sound_AudioInfo actual;  (please fill this in)
137          *    Sound_SampleFlags flags; (set appropriately)
138          */
139     int (*open)(Sound_Sample *sample, const char *ext);
140 
141         /*
142          * Clean up. SDL_sound is done with this sample, so the decoder should
143          *  clean up any resources it allocated. Anything that wasn't
144          *  explicitly allocated by the decoder should be LEFT ALONE, since
145          *  the higher-level SDL_sound layer will clean up its own mess.
146          */
147     void (*close)(Sound_Sample *sample);
148 
149         /*
150          * Get more data from (sample). The decoder should get a pointer to
151          *  the internal structure...
152          *
153          *   Sound_SampleInternal *internal;
154          *   internal = (Sound_SampleInternal *) sample->opaque;
155          *
156          *  ...and then start decoding. Fill in up to desired_frames
157          *  PCM frames of decoded sound into the space pointed to by
158          *  buffer. The encoded data is read in from internal->rw.
159          *
160          * The return value is the number of frames decoded into
161          *  buffer, which can be no more than desired_frames,
162          *  but can be less. If it is less, you should set a state flag:
163          *
164          *   If there's just no more data (end of file, etc), then do:
165          *      sample->flags |= SOUND_SAMPLEFLAG_EOF;
166          *
167          *   If there's an unrecoverable error, then do:
168          *      __Sound_SetError(ERR_EXPLAIN_WHAT_WENT_WRONG);
169          *      sample->flags |= SOUND_SAMPLEFLAG_ERROR;
170          *
171          *   If there's more data, but you'd have to block for considerable
172          *    amounts of time to get at it, or there's a recoverable error,
173          *    then do:
174          *      __Sound_SetError(ERR_EXPLAIN_WHAT_WENT_WRONG);
175          *      sample->flags |= SOUND_SAMPLEFLAG_EAGAIN;
176          *
177          * SDL_sound will not call your read() method for any samples with
178          *  SOUND_SAMPLEFLAG_EOF or SOUND_SAMPLEFLAG_ERROR set. The
179          *  SOUND_SAMPLEFLAG_EAGAIN flag is reset before each call to this
180          *  method.
181          */
182     Uint32 (*read)(Sound_Sample *sample, void* buffer, Uint32 desired_frames);
183 
184         /*
185          * Reset the decoding to the beginning of the stream. Nonzero on
186          *  success, zero on failure.
187          *
188          * The purpose of this method is to allow for higher efficiency than
189          *  an application could get by just recreating the sample externally;
190          *  not only do they not have to reopen the RWops, reallocate buffers,
191          *  and potentially pass the data through several rejecting decoders,
192          *  but certain decoders will not have to recreate their existing
193          *  state (search for metadata, etc) since they already know they
194          *  have a valid audio stream with a given set of characteristics.
195          *
196          * The decoder is responsible for calling seek() on the associated
197          *  SDL_RWops. A failing call to seek() should be the ONLY reason that
198          *  this method should ever fail!
199          */
200     int (*rewind)(Sound_Sample *sample);
201 
202         /*
203          * Reposition the decoding to an arbitrary point. Nonzero on
204          *  success, zero on failure.
205          *
206          * The purpose of this method is to allow for higher efficiency than
207          *  an application could get by just rewinding the sample and
208          *  decoding to a given point.
209          *
210          * The decoder is responsible for calling seek() on the associated
211          *  SDL_RWops.
212          *
213          * If there is an error, try to recover so that the next read will
214          *  continue as if nothing happened.
215          */
216     int (*seek)(Sound_Sample *sample, Uint32 ms);
217 } Sound_DecoderFunctions;
218 
219 typedef void (*MixFunc)(float *dst, void *src, Uint32 frames, float *gains);
220 
221 typedef struct __SOUND_SAMPLEINTERNAL__
222 {
223     Sound_Sample *next;
224     Sound_Sample *prev;
225     SDL_RWops *rw;
226     const Sound_DecoderFunctions *funcs;
227     void *buffer;
228     Uint32 buffer_size;
229     void *decoder_private;
230     Sint32 total_time;
231     Uint32 mix_position;
232     MixFunc mix;
233 } Sound_SampleInternal;
234 
235 
236 /* error messages... */
237 #define ERR_IS_INITIALIZED       "Already initialized"
238 #define ERR_NOT_INITIALIZED      "Not initialized"
239 #define ERR_INVALID_ARGUMENT     "Invalid argument"
240 #define ERR_OUT_OF_MEMORY        "Out of memory"
241 #define ERR_NOT_SUPPORTED        "Operation not supported"
242 #define ERR_UNSUPPORTED_FORMAT   "Sound format unsupported"
243 #define ERR_NOT_A_HANDLE         "Not a file handle"
244 #define ERR_NO_SUCH_FILE         "No such file"
245 #define ERR_PAST_EOF             "Past end of file"
246 #define ERR_IO_ERROR             "I/O error"
247 #define ERR_COMPRESSION          "(De)compression error"
248 #define ERR_PREV_ERROR           "Previous decoding already caused an error"
249 #define ERR_PREV_EOF             "Previous decoding already triggered EOF"
250 #define ERR_CANNOT_SEEK          "Sample is not seekable"
251 
252 /*
253  * Call this to set the message returned by Sound_GetError().
254  *  Please only use the ERR_* constants above, or add new constants to the
255  *  above group, but I want these all in one place.
256  *
257  * Calling this with a NULL argument is a safe no-op.
258  */
259 void __Sound_SetError(const char *err);
260 
261 /*
262  * Call this to convert milliseconds to an actual byte position, based on
263  *  audio data characteristics.
264  */
265 Uint32 __Sound_convertMsToBytePos(Sound_AudioInfo *info, Uint32 ms);
266 
267 /*
268  * Use this if you need a cross-platform stricmp().
269  */
270 int __Sound_strcasecmp(const char *x, const char *y);
271 
272 
273 /* These get used all over for lessening code clutter. */
274 #define BAIL_MACRO(e, r) { __Sound_SetError(e); return r; }
275 #define BAIL_IF_MACRO(c, e, r) if (c) { __Sound_SetError(e); return r; }
276 
277 
278 
279 
280 /*--------------------------------------------------------------------------*/
281 /*--------------------------------------------------------------------------*/
282 /*------------                                              ----------------*/
283 /*------------  You MUST implement the following functions  ----------------*/
284 /*------------        if porting to a new platform.         ----------------*/
285 /*------------     (see platform/unix.c for an example)     ----------------*/
286 /*------------                                              ----------------*/
287 /*--------------------------------------------------------------------------*/
288 /*--------------------------------------------------------------------------*/
289 
290 
291 /* (None, right now.)  */
292 
293 
294 #ifdef __cplusplus
295 extern "C" {
296 #endif
297 
298 #endif /* defined _INCLUDE_SDL_SOUND_INTERNAL_H_ */
299 
300 /* end of SDL_sound_internal.h ... */
301