DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
src/libs/decoders/SDL_sound_internal.h
00001 /*
00002  *  Modified SDL Sound API implementation
00003  *  -------------------------------------
00004  *  Internal function/structure declaration. Do NOT include in your
00005  *  application.
00006  *
00007  *  Copyright (C) 2020       The DOSBox Team
00008  *  Copyright (C) 2018-2019  Kevin R. Croft <krcroft@gmail.com>
00009  *  Copyright (C) 2001-2017  Ryan C. Gordon <icculus@icculus.org>
00010  *
00011  *  This program is free software; you can redistribute it and/or modify
00012  *  it under the terms of the GNU General Public License as published by
00013  *  the Free Software Foundation; either version 2 of the License, or
00014  *  (at your option) any later version.
00015  *
00016  *  This program is distributed in the hope that it will be useful,
00017  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  *  GNU General Public License for more details.
00020  *
00021  *  You should have received a copy of the GNU General Public License along
00022  *  with this program; if not, write to the Free Software Foundation, Inc.,
00023  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00024  */
00025 
00026 #ifndef _INCLUDE_SDL_SOUND_INTERNAL_H_
00027 #define _INCLUDE_SDL_SOUND_INTERNAL_H_
00028 
00029 #ifndef __SDL_SOUND_INTERNAL__
00030 #error Do not include this header from your applications.
00031 #endif
00032 
00033 #include <SDL.h>
00034 
00035 /* SDL 1.2.4 defines this, but better safe than sorry. */
00036 #if (!defined(__inline__))
00037 #  define __inline__
00038 #endif
00039 
00040 #if (defined DEBUG_CHATTER)
00041 #define SNDDBG(x) printf x
00042 #else
00043 #define SNDDBG(x)
00044 #endif
00045 
00046 #if HAVE_ASSERT_H
00047 #  include <assert.h>
00048 #endif
00049 
00050 #ifdef _WIN32_WCE
00051     extern char *strrchr(const char *s, int c);
00052 #   ifdef NDEBUG
00053 #       define assert(x)
00054 #   else
00055 #       define assert(x) if(!x) { fprintf(stderr,"Assertion failed in %s, line %s.\n",__FILE__,__LINE__); fclose(stderr); fclose(stdout); exit(1); }
00056 #   endif
00057 #endif
00058  
00059 
00060 #if (!defined assert)  /* if all else fails. */
00061 #  define assert(x)
00062 #endif
00063 
00064 
00065 /*
00066  * SDL itself only supports mono and stereo output, but hopefully we can
00067  *  raise this value someday...there's probably a lot of assumptions in
00068  *  SDL_sound that rely on it, though.
00069  */
00070 #define MAX_CHANNELS 2
00071 
00072 
00073 typedef struct __SOUND_DECODERFUNCTIONS__
00074 {
00075         /* This is a block of info about your decoder. See SDL_sound.h. */
00076     const Sound_DecoderInfo info;
00077 
00078         /*
00079          * This is called during the Sound_Init() function. Use this to
00080          *  set up any global state that your decoder needs, such as
00081          *  initializing an external library, etc.
00082          *
00083          * Return non-zero if initialization is successful, zero if there's
00084          *  a fatal error. If this method fails, then this decoder is
00085          *  flagged as unavailable until SDL_sound() is shut down and
00086          *  reinitialized, in which case this method will be tried again.
00087          *
00088          * Note that the decoders quit() method won't be called if this
00089          *  method fails, so if you can't intialize, you'll have to clean
00090          *  up the half-initialized state in this method.
00091          */
00092     int (*init)(void);
00093 
00094         /*
00095          * This is called during the Sound_Quit() function. Use this to
00096          *  clean up any global state that your decoder has used during its
00097          *  lifespan.
00098          */
00099     void (*quit)(void);
00100 
00101         /*
00102          * Returns non-zero if (sample) has a valid fileformat that this
00103          *  driver can handle. Zero if this driver can NOT handle the data.
00104          *
00105          * Extension, which may be NULL, is just a hint as to the form of
00106          *  data that is being passed in. Most decoders should determine if
00107          *  they can handle the data by the data itself, but others, like
00108          *  the raw data handler, need this hint to know if they should
00109          *  accept the data in the first place.
00110          *
00111          * (sample)'s (opaque) field should be cast to a Sound_SampleInternal
00112          *  pointer:
00113          *
00114          *   Sound_SampleInternal *internal;
00115          *   internal = (Sound_SampleInternal *) sample->opaque;
00116          *
00117          * Certain fields of sample will be filled in for the decoder before
00118          *  this call, and others should be filled in by the decoder. Some
00119          *  fields are offlimits, and should NOT be modified. The list:
00120          *
00121          * in Sound_SampleInternal section:
00122          *    Sound_Sample *next;  (offlimits)
00123          *    Sound_Sample *prev;  (offlimits)
00124          *    SDL_RWops *rw;       (can use, but do NOT close it)
00125          *    const Sound_DecoderFunctions *funcs; (that's this structure)
00126          *    void *decoder_private; (read and write access)
00127          *
00128          * in rest of Sound_Sample:
00129          *    void *opaque;        (this was internal section, above)
00130          *    const Sound_DecoderInfo *decoder;  (read only)
00131          *    Sound_AudioInfo desired; (read only, usually not needed here)
00132          *    Sound_AudioInfo actual;  (please fill this in)
00133          *    Sound_SampleFlags flags; (set appropriately)
00134          */
00135     int (*open)(Sound_Sample *sample, const char *ext);
00136 
00137         /*
00138          * Clean up. SDL_sound is done with this sample, so the decoder should
00139          *  clean up any resources it allocated. Anything that wasn't
00140          *  explicitly allocated by the decoder should be LEFT ALONE, since
00141          *  the higher-level SDL_sound layer will clean up its own mess.
00142          */
00143     void (*close)(Sound_Sample *sample);
00144 
00145         /*
00146          * Get more data from (sample). The decoder should get a pointer to
00147          *  the internal structure...
00148          *
00149          *   Sound_SampleInternal *internal;
00150          *   internal = (Sound_SampleInternal *) sample->opaque;
00151          *
00152          *  ...and then start decoding. Fill in up to desired_frames
00153          *  PCM frames of decoded sound into the space pointed to by
00154          *  buffer. The encoded data is read in from internal->rw.
00155          *
00156          * The return value is the number of frames decoded into
00157          *  buffer, which can be no more than desired_frames,
00158          *  but can be less. If it is less, you should set a state flag:
00159          *
00160          *   If there's just no more data (end of file, etc), then do:
00161          *      sample->flags |= SOUND_SAMPLEFLAG_EOF;
00162          *
00163          *   If there's an unrecoverable error, then do:
00164          *      __Sound_SetError(ERR_EXPLAIN_WHAT_WENT_WRONG);
00165          *      sample->flags |= SOUND_SAMPLEFLAG_ERROR;
00166          *
00167          *   If there's more data, but you'd have to block for considerable
00168          *    amounts of time to get at it, or there's a recoverable error,
00169          *    then do:
00170          *      __Sound_SetError(ERR_EXPLAIN_WHAT_WENT_WRONG);
00171          *      sample->flags |= SOUND_SAMPLEFLAG_EAGAIN;
00172          *
00173          * SDL_sound will not call your read() method for any samples with
00174          *  SOUND_SAMPLEFLAG_EOF or SOUND_SAMPLEFLAG_ERROR set. The
00175          *  SOUND_SAMPLEFLAG_EAGAIN flag is reset before each call to this
00176          *  method.
00177          */
00178     Uint32 (*read)(Sound_Sample *sample, void* buffer, Uint32 desired_frames);
00179 
00180         /*
00181          * Reset the decoding to the beginning of the stream. Nonzero on
00182          *  success, zero on failure.
00183          *  
00184          * The purpose of this method is to allow for higher efficiency than
00185          *  an application could get by just recreating the sample externally;
00186          *  not only do they not have to reopen the RWops, reallocate buffers,
00187          *  and potentially pass the data through several rejecting decoders,
00188          *  but certain decoders will not have to recreate their existing
00189          *  state (search for metadata, etc) since they already know they
00190          *  have a valid audio stream with a given set of characteristics.
00191          *
00192          * The decoder is responsible for calling seek() on the associated
00193          *  SDL_RWops. A failing call to seek() should be the ONLY reason that
00194          *  this method should ever fail!
00195          */
00196     int (*rewind)(Sound_Sample *sample);
00197 
00198         /*
00199          * Reposition the decoding to an arbitrary point. Nonzero on
00200          *  success, zero on failure.
00201          *  
00202          * The purpose of this method is to allow for higher efficiency than
00203          *  an application could get by just rewinding the sample and 
00204          *  decoding to a given point.
00205          *
00206          * The decoder is responsible for calling seek() on the associated
00207          *  SDL_RWops.
00208          *
00209          * If there is an error, try to recover so that the next read will
00210          *  continue as if nothing happened.
00211          */
00212     int (*seek)(Sound_Sample *sample, Uint32 ms);
00213 } Sound_DecoderFunctions;
00214 
00215 typedef void (*MixFunc)(float *dst, void *src, Uint32 frames, float *gains);
00216 
00217 typedef struct __SOUND_SAMPLEINTERNAL__
00218 {
00219     Sound_Sample *next;
00220     Sound_Sample *prev;
00221     SDL_RWops *rw;
00222     const Sound_DecoderFunctions *funcs;
00223     void *buffer;
00224     Uint32 buffer_size;
00225     void *decoder_private;
00226     Sint32 total_time;
00227     Uint32 mix_position;
00228     MixFunc mix;
00229 } Sound_SampleInternal;
00230 
00231 
00232 /* error messages... */
00233 #define ERR_IS_INITIALIZED       "Already initialized"
00234 #define ERR_NOT_INITIALIZED      "Not initialized"
00235 #define ERR_INVALID_ARGUMENT     "Invalid argument"
00236 #define ERR_OUT_OF_MEMORY        "Out of memory"
00237 #define ERR_NOT_SUPPORTED        "Operation not supported"
00238 #define ERR_UNSUPPORTED_FORMAT   "Sound format unsupported"
00239 #define ERR_NOT_A_HANDLE         "Not a file handle"
00240 #define ERR_NO_SUCH_FILE         "No such file"
00241 #define ERR_PAST_EOF             "Past end of file"
00242 #define ERR_IO_ERROR             "I/O error"
00243 #define ERR_COMPRESSION          "(De)compression error"
00244 #define ERR_PREV_ERROR           "Previous decoding already caused an error"
00245 #define ERR_PREV_EOF             "Previous decoding already triggered EOF"
00246 #define ERR_CANNOT_SEEK          "Sample is not seekable"
00247 
00248 /*
00249  * Call this to set the message returned by Sound_GetError().
00250  *  Please only use the ERR_* constants above, or add new constants to the
00251  *  above group, but I want these all in one place.
00252  *
00253  * Calling this with a NULL argument is a safe no-op.
00254  */
00255 void __Sound_SetError(const char *err);
00256 
00257 /*
00258  * Call this to convert milliseconds to an actual byte position, based on
00259  *  audio data characteristics.
00260  */
00261 Uint32 __Sound_convertMsToBytePos(Sound_AudioInfo *info, Uint32 ms);
00262 
00263 /*
00264  * Use this if you need a cross-platform stricmp().
00265  */
00266 int __Sound_strcasecmp(const char *x, const char *y);
00267 
00268 
00269 /* These get used all over for lessening code clutter. */
00270 #define BAIL_MACRO(e, r) { __Sound_SetError(e); return r; }
00271 #define BAIL_IF_MACRO(c, e, r) if (c) { __Sound_SetError(e); return r; }
00272 
00273 
00274 
00275 
00276 /*--------------------------------------------------------------------------*/
00277 /*--------------------------------------------------------------------------*/
00278 /*------------                                              ----------------*/
00279 /*------------  You MUST implement the following functions  ----------------*/
00280 /*------------        if porting to a new platform.         ----------------*/
00281 /*------------     (see platform/unix.c for an example)     ----------------*/
00282 /*------------                                              ----------------*/
00283 /*--------------------------------------------------------------------------*/
00284 /*--------------------------------------------------------------------------*/
00285 
00286 
00287 /* (None, right now.)  */
00288 
00289 
00290 #ifdef __cplusplus
00291 extern "C"
00292 #endif
00293 
00294 #endif /* defined _INCLUDE_SDL_SOUND_INTERNAL_H_ */
00295 
00296 /* end of SDL_sound_internal.h ... */
00297