From 7e8040a0ddc2c1a9ce8fae643cdd8a9334daa18a Mon Sep 17 00:00:00 2001 From: avolkov Date: Wed, 8 Oct 2003 10:41:10 +0000 Subject: [PATCH] Sound decoders refactoring; The decoders are now virtualized, the high-level decoding code is unified and any format is theoretically streamable. git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@1266 8092fc87-c524-0410-9efc-e669fe64eaf9 --- sc2/src/sc2code/libs/sound/decoders/Makeinfo | 2 +- sc2/src/sc2code/libs/sound/decoders/decoder.c | 1412 ++++++++--------- sc2/src/sc2code/libs/sound/decoders/decoder.h | 68 +- sc2/src/sc2code/libs/sound/decoders/dukaud.c | 434 +++-- sc2/src/sc2code/libs/sound/decoders/dukaud.h | 35 +- sc2/src/sc2code/libs/sound/decoders/modaud.c | 228 +++ sc2/src/sc2code/libs/sound/decoders/modaud.h | 26 + sc2/src/sc2code/libs/sound/decoders/oggaud.c | 256 +++ sc2/src/sc2code/libs/sound/decoders/oggaud.h | 26 + sc2/src/sc2code/libs/sound/decoders/wav.c | 395 +++-- sc2/src/sc2code/libs/sound/decoders/wav.h | 9 +- sc2/src/sc2code/libs/sound/music.c | 3 +- .../sc2code/libs/sound/openal/sound_openal.c | 2 +- sc2/src/sc2code/libs/sound/trackplayer.c | 4 +- 14 files changed, 1824 insertions(+), 1076 deletions(-) create mode 100644 sc2/src/sc2code/libs/sound/decoders/modaud.c create mode 100644 sc2/src/sc2code/libs/sound/decoders/modaud.h create mode 100644 sc2/src/sc2code/libs/sound/decoders/oggaud.c create mode 100644 sc2/src/sc2code/libs/sound/decoders/oggaud.h diff --git a/sc2/src/sc2code/libs/sound/decoders/Makeinfo b/sc2/src/sc2code/libs/sound/decoders/Makeinfo index dad555470..9ccbb11d4 100644 --- a/sc2/src/sc2code/libs/sound/decoders/Makeinfo +++ b/sc2/src/sc2code/libs/sound/decoders/Makeinfo @@ -1,2 +1,2 @@ uqm_SUBDIRS="mikmod" -uqm_CFILES="decoder.c wav.c dukaud.c" +uqm_CFILES="decoder.c wav.c dukaud.c modaud.c oggaud.c" diff --git a/sc2/src/sc2code/libs/sound/decoders/decoder.c b/sc2/src/sc2code/libs/sound/decoders/decoder.c index 560d26f4c..fc00d1185 100644 --- a/sc2/src/sc2code/libs/sound/decoders/decoder.c +++ b/sc2/src/sc2code/libs/sound/decoders/decoder.c @@ -23,61 +23,124 @@ #include #endif -#include #include -#include -#include +#include #include "port.h" #include "libs/misc.h" -#include "libs/uio.h" #include "decoder.h" #include "wav.h" -#include "libs/sound/sound_common.h" -#include "mikmod/mikmod.h" #include "dukaud.h" +#include "modaud.h" +#include "oggaud.h" extern bool fileExists2(uio_DirHandle *dir, const char *fileName); // Can't '#include "libs/file.h"' due to some type conflicts. -MIKMODAPI extern struct MDRIVER drv_openal; -static char *decoder_info_wav = "Wav"; -static char *decoder_info_mod = "MikMod"; -static char *decoder_info_ogg = "Ogg Vorbis"; -static char *decoder_info_nul = "None"; -static char *decoder_info_duk = "DukAud"; +#define THIS_PTR TFB_SoundDecoder* + +static const char* bufa_GetName (void); +static bool bufa_InitModule (int flags); +static void bufa_TermModule (); +static uint32 bufa_GetStructSize (void); +static int bufa_GetError (THIS_PTR); +static bool bufa_Init (THIS_PTR); +static void bufa_Term (THIS_PTR); +static bool bufa_Open (THIS_PTR, uio_DirHandle *dir, const char *filename); +static void bufa_Close (THIS_PTR); +static int bufa_Decode (THIS_PTR, void* buf, sint32 bufsize); +static uint32 bufa_Seek (THIS_PTR, uint32 pcm_pos); +static uint32 bufa_GetFrame (THIS_PTR); + +TFB_SoundDecoderFuncs bufa_DecoderVtbl = +{ + bufa_GetName, + bufa_InitModule, + bufa_TermModule, + bufa_GetStructSize, + bufa_GetError, + bufa_Init, + bufa_Term, + bufa_Open, + bufa_Close, + bufa_Decode, + bufa_Seek, + bufa_GetFrame, +}; + +typedef struct tfb_bufsounddecoder +{ + // always the first member + TFB_SoundDecoder decoder; + + // private + void* data; + uint32 max_pcm; + uint32 cur_pcm; + +} TFB_BufSoundDecoder; + +#define SD_MIN_SIZE (sizeof (TFB_BufSoundDecoder)) + +static const char* nula_GetName (void); +static bool nula_InitModule (int flags); +static void nula_TermModule (); +static uint32 nula_GetStructSize (void); +static int nula_GetError (THIS_PTR); +static bool nula_Init (THIS_PTR); +static void nula_Term (THIS_PTR); +static bool nula_Open (THIS_PTR, uio_DirHandle *dir, const char *filename); +static void nula_Close (THIS_PTR); +static int nula_Decode (THIS_PTR, void* buf, sint32 bufsize); +static uint32 nula_Seek (THIS_PTR, uint32 pcm_pos); +static uint32 nula_GetFrame (THIS_PTR); + +TFB_SoundDecoderFuncs nula_DecoderVtbl = +{ + nula_GetName, + nula_InitModule, + nula_TermModule, + nula_GetStructSize, + nula_GetError, + nula_Init, + nula_Term, + nula_Open, + nula_Close, + nula_Decode, + nula_Seek, + nula_GetFrame, +}; + +typedef struct tfb_nullsounddecoder +{ + // always the first member + TFB_SoundDecoder decoder; + + // private + uint32 cur_pcm; + +} TFB_NullSoundDecoder; + +#undef THIS_PTR + + +static struct sd_DecoderInfo +{ + const char* ext; + TFB_SoundDecoderFuncs* funcs; +} +sd_decoders[] = +{ + {"wav", &wava_DecoderVtbl}, + {"mod", &moda_DecoderVtbl}, + {"ogg", &ova_DecoderVtbl}, + {"duk", &duka_DecoderVtbl}, + {NULL, NULL} // null term +}; + TFB_DecoderFormats decoder_formats; -static size_t ogg_read (void *ptr, size_t size, size_t nmemb, void *datasource) -{ - return uio_fread ((uio_Stream *) ptr, size, nmemb, datasource); -} - -static int ogg_seek (void *datasource, ogg_int64_t offset, int whence) -{ - long off = (long) offset; - return uio_fseek ((uio_Stream *) datasource, off, whence); -} - -static int ogg_close (void *datasource) -{ - return uio_fclose ((uio_Stream *) datasource); -} - -static long ogg_tell(void *datasource) -{ - return uio_ftell ((uio_Stream *) datasource); -} - -static const ov_callbacks ogg_callbacks = -{ - ogg_read, - ogg_seek, - ogg_close, - ogg_tell, -}; - /* change endianness of 16bit words * Only works optimal when 'data' is aligned on a 32 bits boundary. */ @@ -101,10 +164,19 @@ SoundDecoder_SwapWords (uint16* data, uint32 size) } } -sint32 SoundDecoder_Init (int flags, TFB_DecoderFormats *formats) +const char* +SoundDecoder_GetName (TFB_SoundDecoder *decoder) { - MikMod_RegisterDriver (&drv_openal); - MikMod_RegisterAllLoaders (); + if (!decoder || !decoder->funcs) + return "(Null)"; + return decoder->funcs->GetName (); +} + +sint32 +SoundDecoder_Init (int flags, TFB_DecoderFormats *formats) +{ + struct sd_DecoderInfo* info; + sint32 ret = 0; if (!formats) { @@ -113,802 +185,628 @@ sint32 SoundDecoder_Init (int flags, TFB_DecoderFormats *formats) } decoder_formats = *formats; - if (flags & TFB_SOUNDFLAGS_HQAUDIO) + for (info = sd_decoders; info->ext; info++) { - md_mode = DMODE_HQMIXER|DMODE_STEREO|DMODE_16BITS|DMODE_INTERP|DMODE_SURROUND; - md_mixfreq = 44100; - md_reverb = 1; - } - else if (flags & TFB_SOUNDFLAGS_LQAUDIO) - { - md_mode = DMODE_SOFT_MUSIC|DMODE_STEREO|DMODE_16BITS; - md_mixfreq = 22050; - md_reverb = 0; - } - else - { - md_mode = DMODE_SOFT_MUSIC|DMODE_STEREO|DMODE_16BITS|DMODE_INTERP; - md_mixfreq = 44100; - md_reverb = 0; - } - - md_pansep = 64; - - if (MikMod_Init ("")) - { - fprintf (stderr, "SoundDecoder_Init(): MikMod_Init failed, %s\n", - MikMod_strerror (MikMod_errno)); - return 1; + if (!info->funcs->InitModule (flags)) + { + fprintf (stderr, "SoundDecoder_Init(): %s audio decoder init failed\n", + info->funcs->GetName ()); + ret = 1; + } } return 0; } -void SoundDecoder_Uninit (void) +void +SoundDecoder_Uninit (void) { - MikMod_Exit (); + struct sd_DecoderInfo* info; + + for (info = sd_decoders; info->ext; info++) + info->funcs->TermModule (); } -TFB_SoundDecoder* SoundDecoder_Load (uio_DirHandle *dir, char *filename, +TFB_SoundDecoder* +SoundDecoder_Load (uio_DirHandle *dir, char *filename, uint32 buffer_size, uint32 startTime, sint32 runTime) { - int i; + const char* pext; + struct sd_DecoderInfo* info; + TFB_SoundDecoderFuncs* funcs; + TFB_SoundDecoder* decoder; + uint32 struct_size; + + pext = strrchr (filename, '.'); + if (!pext) + { + fprintf (stderr, "SoundDecoder_Load(): Unknown file type (%s)\n", + filename); + return NULL; + } + ++pext; + + for (info = sd_decoders; + info->ext && strcmp (info->ext, pext) != 0; + ++info) + ; + if (!info->ext) + { + fprintf (stderr, "SoundDecoder_Load(): Unsupported file type (%s)\n", + filename); + return NULL; + } + funcs = info->funcs; - i = strlen (filename) - 3; if (!fileExists2 (dir, filename)) { if (runTime) { - TFB_SoundDecoder *decoder; runTime = abs (runTime); - decoder = (TFB_SoundDecoder *) HMalloc (sizeof (TFB_SoundDecoder)); - decoder->buffer = HCalloc (buffer_size); - decoder->buffer_size = buffer_size; - decoder->frequency = 11025; - decoder->looping = false; - decoder->error = SOUNDDECODER_OK; - decoder->length = (float)(runTime / 1000.0); - - decoder->start_sample = 0; - decoder->end_sample = (unsigned long)(decoder->length * decoder->frequency); - - decoder->format = decoder_formats.mono16; - decoder->pos = 0; - - decoder->decoder_info = decoder_info_nul; - decoder->type = SOUNDDECODER_NULL; - decoder->dir = dir; - decoder->filename = (char *) HMalloc (strlen (filename) + 1); - strcpy (decoder->filename, filename); - decoder->data = NULL; - return decoder; + startTime = 0; + funcs = &nula_DecoderVtbl; } else { - fprintf (stderr, "SoundDecoder_Load(): %s doesn't exist\n", filename); + fprintf (stderr, "SoundDecoder_Load(): %s does not exist\n", + filename); return NULL; } } - if (!strcmp (&filename[i], "wav")) + struct_size = info->funcs->GetStructSize (); + if (struct_size < SD_MIN_SIZE) + struct_size = SD_MIN_SIZE; + + decoder = (TFB_SoundDecoder*) HCalloc (struct_size); + decoder->funcs = funcs; + if (!decoder->funcs->Init (decoder)) { - TFB_SoundDecoder *decoder; - - //fprintf (stderr, "SoundDecoder_Load(): %s interpreted as wav\n", filename); - - decoder = (TFB_SoundDecoder *) HMalloc (sizeof (TFB_SoundDecoder)); - decoder->buffer = NULL; - decoder->buffer_size = 0; - decoder->format = 0; - decoder->frequency = 0; - decoder->looping = false; - decoder->error = SOUNDDECODER_OK; - decoder->length = 0; // FIXME should be calculated - decoder->decoder_info = decoder_info_wav; - decoder->type = SOUNDDECODER_WAV; - decoder->dir = dir; - decoder->filename = (char *) HMalloc (strlen (filename) + 1); - decoder->start_sample = 0; - decoder->end_sample = 0; - decoder->pos = 0; - strcpy (decoder->filename, filename); - - return decoder; + fprintf (stderr, "SoundDecoder_Load(): " + "%s decoder instance failed init\n", + decoder->funcs->GetName ()); + HFree (decoder); + return NULL; } - else if (!strcmp (&filename[i], "mod")) + + if (!decoder->funcs->Open (decoder, dir, filename)) { - TFB_SoundDecoder *decoder; - MODULE *mod; - - //fprintf (stderr, "SoundDecoder_Load(): %s interpreted as mod\n", filename); - - mod = Player_Load (dir, filename, 4, 0); - if (!mod) - { - fprintf (stderr, "SoundDecoder_Load(): couldn't load %s\n", filename); - return NULL; - } - - mod->extspd = 1; - mod->panflag = 1; - mod->wrap = 0; - mod->loop = 1; - - decoder = (TFB_SoundDecoder *) HMalloc (sizeof (TFB_SoundDecoder)); - decoder->buffer = HMalloc (buffer_size); - decoder->buffer_size = buffer_size; - decoder->format = decoder_formats.stereo16; - decoder->frequency = md_mixfreq; - decoder->looping = false; - decoder->error = SOUNDDECODER_OK; - decoder->length = 0; // FIXME way to obtain this from mikmod? - decoder->decoder_info = decoder_info_mod; - decoder->type = SOUNDDECODER_MOD; - decoder->dir = dir; - decoder->filename = (char *) HMalloc (strlen (filename) + 1); - decoder->start_sample = 0; - decoder->end_sample = 0; - decoder->pos = 0; - strcpy (decoder->filename, filename); - decoder->data = mod; - - return decoder; - } - else if (!strcmp (&filename[i], "ogg")) - { - int rc; - uio_Stream *vfp; - OggVorbis_File *vf; - vorbis_info *vinfo; - TFB_SoundDecoder *decoder; - - //fprintf (stderr, "SoundDecoder_Load(): %s interpreted as ogg\n", filename); - - vf = (OggVorbis_File *) HMalloc (sizeof (OggVorbis_File)); - if (!vf) - { - fprintf (stderr, "SoundDecoder_Load(): couldn't allocate mem for OggVorbis_File\n"); - return NULL; - } - - vfp = uio_fopen (dir, filename, "rb"); - if (vfp == NULL) - { - fprintf (stderr, "SoundDecoder_Load(): couldn't open %s\n", filename); - HFree (vf); - return NULL; - } - - rc = ov_open_callbacks (vfp, vf, NULL, 0, ogg_callbacks); - if (rc != 0) - { - fprintf (stderr, "SoundDecoder_Load(): ov_open_callbacks failed for %s, error code %d\n", filename, rc); - uio_fclose (vfp); - HFree (vf); - return NULL; - } - - vinfo = ov_info (vf, -1); - if (!vinfo) - { - fprintf (stderr, "SoundDecoder_Load(): failed to retrieve ogg bitstream info for %s\n", filename); - ov_clear (vf); - HFree (vf); - return NULL; - } - - //fprintf (stderr, "SoundDecoder_Load(): ogg bitstream version %d, channels %d, rate %d, length %.2f seconds\n", vinfo->version, vinfo->channels, vinfo->rate, ov_time_total (vf, -1)); - - decoder = (TFB_SoundDecoder *) HMalloc (sizeof (TFB_SoundDecoder)); - decoder->buffer = HMalloc (buffer_size); - decoder->buffer_size = buffer_size; - decoder->frequency = vinfo->rate; - decoder->looping = false; - decoder->error = SOUNDDECODER_OK; - decoder->length = (float) ov_time_total (vf, -1) - (startTime / 1000.0f); - if (runTime > 0 && runTime / 1000.0 < decoder->length) - decoder->length = (float)(runTime / 1000.0); - - decoder->start_sample = decoder->frequency * startTime / 1000; - decoder->end_sample = decoder->start_sample + - (unsigned long)(decoder->length * decoder->frequency); - if (decoder->start_sample) - ov_pcm_seek (vf, decoder->start_sample); - - if (vinfo->channels == 1) - { - decoder->format = decoder_formats.mono16; - decoder->pos = decoder->start_sample * 2; - } - else - { - decoder->format = decoder_formats.stereo16; - decoder->pos = decoder->start_sample * 4; - } - - decoder->decoder_info = decoder_info_ogg; - decoder->type = SOUNDDECODER_OGG; - decoder->dir = dir; - decoder->filename = (char *) HMalloc (strlen (filename) + 1); - strcpy (decoder->filename, filename); - decoder->data = vf; - - return decoder; - } - else if (!strcmp (&filename[i], "duk")) - { - TFB_SoundDecoder *decoder; - DukAud_Track* track; - - track = duka_openTrack (dir, filename); - if (!track) - { - fprintf (stderr, "SoundDecoder_Load(): couldn't load %s\n", filename); - return NULL; - } - - decoder = (TFB_SoundDecoder *) HMalloc (sizeof (TFB_SoundDecoder)); - decoder->buffer = HMalloc (buffer_size); - decoder->buffer_size = buffer_size; - decoder->frequency = track->rate; - decoder->looping = false; - decoder->error = SOUNDDECODER_OK; - decoder->length = track->length - (startTime / 1000.0f); - decoder->start_sample = 0; - decoder->end_sample = 0; - decoder->pos = 0; - - if (track->channels == 1) - decoder->format = decoder_formats.mono16; - else - decoder->format = decoder_formats.stereo16; - - decoder->decoder_info = decoder_info_duk; - decoder->type = SOUNDDECODER_DUK; - decoder->dir = dir; - decoder->filename = (char *) HMalloc (strlen (filename) + 1); - strcpy (decoder->filename, filename); - decoder->data = track; - - return decoder; - } - else - { - fprintf (stderr, "SoundDecoder_Load(): %s file format is unsupported\n", filename); + fprintf (stderr, "SoundDecoder_Load(): " + "%s decoder could not load %s\n", + decoder->funcs->GetName (), filename); + decoder->funcs->Term (decoder); + HFree (decoder); + return NULL; } - return NULL; + decoder->buffer = HMalloc (buffer_size); + decoder->buffer_size = buffer_size; + decoder->looping = false; + decoder->error = SOUNDDECODER_OK; + decoder->dir = dir; + decoder->filename = (char *) HMalloc (strlen (filename) + 1); + strcpy (decoder->filename, filename); + + if (decoder->is_null) + { // fake decoder, keeps voiceovers and etc. going + decoder->length = (float) (runTime / 1000.0); + } + + decoder->length -= startTime / 1000.0f; + if (runTime > 0 && runTime / 1000.0 < decoder->length) + decoder->length = (float)(runTime / 1000.0); + + decoder->start_sample = decoder->frequency * startTime / 1000; + decoder->end_sample = decoder->start_sample + + (unsigned long)(decoder->length * decoder->frequency); + if (decoder->start_sample != 0) + decoder->funcs->Seek (decoder, decoder->start_sample); + + if (decoder->format == decoder_formats.mono8) + decoder->bytes_per_samp = 1; + else if (decoder->format == decoder_formats.mono16) + decoder->bytes_per_samp = 2; + else if (decoder->format == decoder_formats.stereo8) + decoder->bytes_per_samp = 2; + else if (decoder->format == decoder_formats.stereo16) + decoder->bytes_per_samp = 4; + + decoder->pos = decoder->start_sample * decoder->bytes_per_samp; + + return decoder; } -uint32 SoundDecoder_Decode (TFB_SoundDecoder *decoder) +uint32 +SoundDecoder_Decode (TFB_SoundDecoder *decoder) { - switch (decoder->type) + long decoded_bytes; + long rc; + long buffer_size; + uint32 max_bytes = UINT32_MAX; + uint8 *buffer; + + if (!decoder || !decoder->funcs) { - case SOUNDDECODER_WAV: - { - fprintf (stderr, "SoundDecoder_Decode(): unimplemented for wav\n"); - break; - } - case SOUNDDECODER_MOD: - { - MODULE *mod = (MODULE *) decoder->data; - uint32 decoded_bytes; - - Player_Start (mod); - if (!Player_Active()) - { - if (decoder->looping) - { - fprintf (stderr, "SoundDecoder_Decode(): looping %s\n", decoder->filename); - Player_SetPosition (0); - Player_Start (mod); - } - else - { - fprintf (stderr, "SoundDecoder_Decode(): eof for %s\n", decoder->filename); - decoder->error = SOUNDDECODER_EOF; - return 0; - } - } - decoder->error = SOUNDDECODER_OK; - decoded_bytes = VC_WriteBytes (decoder->buffer, decoder->buffer_size); - - /* MikMod produces output in machine byte-order - * may need to do a word-swap - */ - if (decoded_bytes > 0 && - decoder_formats.big_endian != decoder_formats.want_big_endian && - (decoder->format == decoder_formats.stereo16 || - decoder->format == decoder_formats.mono16)) - { - SoundDecoder_SwapWords ( - decoder->buffer, decoded_bytes); - } - return decoded_bytes; - } - case SOUNDDECODER_OGG: - { - OggVorbis_File *vf = (OggVorbis_File *) decoder->data; - uint32 decoded_bytes = 0, count = 0; - long rc; - int bitstream; - uint32 max_bytes, buffer_size, close_on_done = 0; - char *buffer = (char *) decoder->buffer; - - if (! decoder->looping) - { - if (decoder->format == decoder_formats.stereo16) - max_bytes = decoder->end_sample * 4; - else - max_bytes = decoder->end_sample * 2; - if (max_bytes - decoder->pos < decoder->buffer_size) - { - buffer_size = max_bytes - decoder->pos; - close_on_done = 1; - } - else - { - buffer_size = decoder->buffer_size; - } - } - else - buffer_size = decoder->buffer_size; - - if (buffer_size == 0) - { // nothing more to decode - decoder->error = SOUNDDECODER_EOF; - return 0; - } - - while (decoded_bytes < buffer_size) - { - /* Produce output in requested byte-order */ - rc = ov_read (vf, &buffer[decoded_bytes], - buffer_size - decoded_bytes, - decoder_formats.want_big_endian, 2, 1, &bitstream); - if (rc < 0) - { - decoder->error = SOUNDDECODER_ERROR; - fprintf (stderr, "SoundDecoder_Decode(): error decoding %s, code %ld\n", decoder->filename, rc); - return decoded_bytes; - } - if (rc == 0 || (close_on_done && buffer_size == (decoded_bytes + rc))) - { - if (close_on_done) - { - decoded_bytes += rc; - } - if (decoder->looping) - { - SoundDecoder_Rewind (decoder); - if (decoder->error) - { - fprintf (stderr, "SoundDecoder_Decode(): tried to loop %s but couldn't rewind, error code %d\n", decoder->filename, decoder->error); - } - else - { - fprintf (stderr, "SoundDecoder_Decode(): looping %s\n", decoder->filename); - count++; - continue; - } - } - else - decoder->pos += decoded_bytes; - - fprintf (stderr, "SoundDecoder_Decode(): eof for %s\n", decoder->filename); - decoder->error = SOUNDDECODER_EOF; - return decoded_bytes; - } - - decoded_bytes += rc; - //fprintf (stderr, "iter %d rc %d decoded_bytes %d remaining %d\n", count, rc, decoded_bytes, decoder->buffer_size - decoded_bytes); - count++; - } - decoder->pos += decoded_bytes; - decoder->error = SOUNDDECODER_OK; - //fprintf (stderr, "SoundDecoder_Decode(): decoded %d bytes from %s\n", decoded_bytes, decoder->filename); - return decoded_bytes; - } - case SOUNDDECODER_DUK: - { - DukAud_Track *track = (DukAud_Track *) decoder->data; - uint32 decoded_bytes = 0; - sint32 rc; - - rc = duka_readData (track, decoder->buffer, decoder->buffer_size); - if (rc < 0) - { - decoder->error = SOUNDDECODER_ERROR; - fprintf (stderr, "SoundDecoder_Decode(): error decoding %s, code %d\n", decoder->filename, rc); - return decoded_bytes; - } - decoded_bytes = rc; - decoder->pos += decoded_bytes; - decoder->error = rc > 0 ? SOUNDDECODER_OK : SOUNDDECODER_EOF; - //fprintf (stderr, "SoundDecoder_Decode(): decoded %d bytes from %s\n", decoded_bytes, decoder->filename); - - /* DukAud produces output in machine byte-order - * may need to do a word-swap - */ - if (decoded_bytes > 0 && - decoder_formats.big_endian != decoder_formats.want_big_endian && - (decoder->format == decoder_formats.stereo16 || - decoder->format == decoder_formats.mono16)) - { - SoundDecoder_SwapWords ( - decoder->buffer, decoded_bytes); - } - return decoded_bytes; - } - case SOUNDDECODER_NULL: - { - uint32 max_bytes; - max_bytes = decoder->end_sample * 2; - if (max_bytes - decoder->pos <= decoder->buffer_size) - { - uint32 bufsize = max_bytes - decoder->pos; - decoder->pos = max_bytes; - decoder->error = SOUNDDECODER_EOF; - return (bufsize); - } - else - { - decoder->pos += decoder->buffer_size; - decoder->error = SOUNDDECODER_OK; - return (decoder->buffer_size); - } - } - case SOUNDDECODER_BUF: - decoder->buffer = (char *)decoder->data + decoder->pos; - decoder->error = SOUNDDECODER_EOF; - return (decoder->buffer_size - decoder->pos); - default: - { - fprintf (stderr, "SoundDecoder_Decode(): unknown type %d\n", decoder->type); - break; - } + fprintf (stderr, "SoundDecoder_Decode(): null or bad decoder\n"); + return 0; } - decoder->error = SOUNDDECODER_ERROR; - return 0; -} - -uint32 SoundDecoder_DecodeAll (TFB_SoundDecoder *decoder) -{ - switch (decoder->type) + buffer = (uint8*) decoder->buffer; + buffer_size = decoder->buffer_size; + if (!decoder->looping && decoder->end_sample > 0) { - case SOUNDDECODER_WAV: + max_bytes = decoder->end_sample * decoder->bytes_per_samp; + if (max_bytes - decoder->pos < decoder->buffer_size) + buffer_size = max_bytes - decoder->pos; + } + + if (buffer_size == 0) + { // nothing more to decode + decoder->error = SOUNDDECODER_EOF; + return 0; + } + + for (decoded_bytes = 0, rc = 1; rc > 0 && decoded_bytes < buffer_size; ) + { + rc = decoder->funcs->Decode (decoder, buffer + decoded_bytes, + buffer_size - decoded_bytes); + if (rc < 0) { - LoadWAVFile (decoder->dir, decoder->filename, &decoder->format, - &decoder->buffer, &decoder->buffer_size, - &decoder->frequency, decoder_formats.want_big_endian); - - if (decoder->buffer_size != 0) - { - decoder->type = SOUNDDECODER_BUF; - decoder->data = decoder->buffer; - decoder->pos = 0; - decoder->error = SOUNDDECODER_OK; - } - else - { - decoder->error = SOUNDDECODER_ERROR; - } - - return decoder->buffer_size; + fprintf (stderr, "SoundDecoder_Decode(): " + "error decoding %s, code %ld\n", + decoder->filename, rc); } - case SOUNDDECODER_MOD: - { - fprintf (stderr, "SoundDecoder_DecodeAll(): unimplemented for mod\n"); - break; - } - case SOUNDDECODER_OGG: - { - OggVorbis_File *vf = (OggVorbis_File *) decoder->data; - uint32 decoded_bytes = 0; - long rc; - int bitstream; - uint32 reqbufsize = decoder->buffer_size; - + else if (rc == 0) + { // probably EOF if (decoder->looping) { - fprintf (stderr, "SoundDecoder_DecodeAll(): " - "called for %s with looping\n", decoder->filename); - return 0; - } - - if (reqbufsize < 4096) - reqbufsize = 4096; - -#ifdef DEBUG - if (reqbufsize < 16384) - fprintf (stderr, "SoundDecoder_DecodeAll(): WARNING, " - "called with a small buffer (%u)\n", reqbufsize); -#endif - - for (rc = 1; rc > 0; ) - { - if (decoded_bytes >= decoder->buffer_size) - { // need to grow buffer - decoder->buffer_size += reqbufsize; - decoder->buffer = HRealloc ( - decoder->buffer, decoder->buffer_size); - } - - rc = ov_read (vf, (char*)decoder->buffer + decoded_bytes, - decoder->buffer_size - decoded_bytes, - decoder_formats.want_big_endian, 2, 1, &bitstream); - if (rc < 0) + SoundDecoder_Rewind (decoder); + if (decoder->error) { - decoder->error = SOUNDDECODER_ERROR; - fprintf (stderr, "SoundDecoder_DecodeAll(): " - "error decoding %s, code %ld\n", - decoder->filename, rc); - return decoded_bytes; + fprintf (stderr, "SoundDecoder_Decode(): " + "tried to loop %s but couldn't rewind, error code %d\n", + decoder->filename, decoder->error); + } + else + { + fprintf (stderr, "SoundDecoder_Decode(): " + "looping %s\n", decoder->filename); + rc = 1; // prime the loop again } - - decoded_bytes += rc; } - - decoder->buffer_size = decoded_bytes; - ov_clear (vf); - HFree (vf); - decoder->type = SOUNDDECODER_BUF; - decoder->data = decoder->buffer; - decoder->pos = 0; - - decoder->error = SOUNDDECODER_OK; - return decoded_bytes; - break; + else + { + fprintf (stderr, "SoundDecoder_Decode(): eof for %s\n", + decoder->filename); + } } - case SOUNDDECODER_DUK: - { - fprintf (stderr, "SoundDecoder_DecodeAll(): unimplemented for duk\n"); - break; - } - case SOUNDDECODER_NULL: - { - decoder->error = SOUNDDECODER_OK; - return (decoder->end_sample * 2); - break; - } - default: - { - fprintf (stderr, "SoundDecoder_DecodeAll(): unknown type %d\n", decoder->type); - break; + else + { // some bytes decoded + decoded_bytes += rc; } } + decoder->pos += decoded_bytes; + if (rc < 0) + decoder->error = SOUNDDECODER_ERROR; + else if (rc == 0 || decoder->pos >= max_bytes) + decoder->error = SOUNDDECODER_EOF; + else + decoder->error = SOUNDDECODER_OK; - decoder->error = SOUNDDECODER_ERROR; - return 0; + if (decoder->need_swap && decoded_bytes > 0 && + (decoder->format == decoder_formats.stereo16 || + decoder->format == decoder_formats.mono16)) + { + SoundDecoder_SwapWords ( + decoder->buffer, decoded_bytes); + } + + return decoded_bytes; } -void SoundDecoder_Rewind (TFB_SoundDecoder *decoder) +uint32 +SoundDecoder_DecodeAll (TFB_SoundDecoder *decoder) +{ + uint32 decoded_bytes; + long rc; + uint32 reqbufsize; + + if (!decoder || !decoder->funcs) + { + fprintf (stderr, "SoundDecoder_DecodeAll(): null or bad decoder\n"); + return 0; + } + + reqbufsize = decoder->buffer_size; + + if (decoder->looping) + { + fprintf (stderr, "SoundDecoder_DecodeAll(): " + "called for %s with looping\n", decoder->filename); + return 0; + } + + if (reqbufsize < 4096) + reqbufsize = 4096; + +#ifdef DEBUG + if (reqbufsize < 16384) + fprintf (stderr, "SoundDecoder_DecodeAll(): WARNING, " + "called with a small buffer (%u)\n", reqbufsize); +#endif + + for (decoded_bytes = 0, rc = 1; rc > 0; ) + { + if (decoded_bytes >= decoder->buffer_size) + { // need to grow buffer + decoder->buffer_size += reqbufsize; + decoder->buffer = HRealloc ( + decoder->buffer, decoder->buffer_size); + } + + rc = decoder->funcs->Decode (decoder, + (uint8*) decoder->buffer + decoded_bytes, + decoder->buffer_size - decoded_bytes); + + if (rc > 0) + decoded_bytes += rc; + } + decoder->buffer_size = decoded_bytes; + decoder->pos += decoded_bytes; + + if (decoder->need_swap && decoded_bytes > 0 && + (decoder->format == decoder_formats.stereo16 || + decoder->format == decoder_formats.mono16)) + { + SoundDecoder_SwapWords ( + decoder->buffer, decoded_bytes); + } + + if (rc < 0) + { + decoder->error = SOUNDDECODER_ERROR; + fprintf (stderr, "SoundDecoder_DecodeAll(): " + "error decoding %s, code %ld\n", + decoder->filename, rc); + return decoded_bytes; + } + + // switch to Buffer decoder + decoder->funcs->Close (decoder); + decoder->funcs->Term (decoder); + + decoder->funcs = &bufa_DecoderVtbl; + decoder->funcs->Init (decoder); + decoder->pos = 0; + decoder->start_sample = 0; + decoder->error = SOUNDDECODER_OK; + + return decoded_bytes; +} + +void +SoundDecoder_Rewind (TFB_SoundDecoder *decoder) { SoundDecoder_Seek (decoder, 0); } // seekTime is specified in mili-seconds -void SoundDecoder_Seek (TFB_SoundDecoder *decoder, uint32 seekTime) +void +SoundDecoder_Seek (TFB_SoundDecoder *decoder, uint32 seekTime) { - switch (decoder->type) - { - case SOUNDDECODER_WAV: - { - fprintf (stderr, "SoundDecoder_Seek(): unimplemented for wav\n"); - break; - } - case SOUNDDECODER_MOD: - { - MODULE *mod = (MODULE *)decoder->data; - Player_Start (mod); - if (seekTime) - fprintf (stderr, "SoundDecoder_Seek(): non-zero seek positions not supported for mod\n"); - Player_SetPosition (0); - //fprintf (stderr, "SoundDecoder_Rewind(): rewound %s\n", decoder->filename); - decoder->error = SOUNDDECODER_OK; - return; - } - case SOUNDDECODER_OGG: - { - int err; - uint32 pcm_pos = 0; - OggVorbis_File *vf = (OggVorbis_File *) decoder->data; - if (seekTime) - pcm_pos = seekTime * decoder->frequency / 1000; - if ((err = ov_pcm_seek (vf, decoder->start_sample + pcm_pos)) != 0) - { - fprintf (stderr, "SoundDecoder_Seek(): couldn't seek %s, error code %d\n", decoder->filename, err); - break; - } - if (decoder->format == decoder_formats.mono16) - decoder->pos = (pcm_pos + decoder->start_sample) * 2; - else - decoder->pos = (pcm_pos + decoder->start_sample) * 4; + uint32 pcm_pos; - //fprintf (stderr, "SoundDecoder_Seek(): %s (start: %d pos: %d end: %d)\n", - // decoder->filename, decoder->start_sample, pcm_pos, decoder->end_sample); - decoder->error = SOUNDDECODER_OK; - return; - } - case SOUNDDECODER_DUK: - { - DukAud_Track* track = (DukAud_Track*) decoder->data; - - if (duka_seekTrack (track, (float)seekTime / 1000.0f)) - { - decoder->pos = seekTime * decoder->frequency * 2 / 1000; - if (decoder->format == decoder_formats.stereo16) - decoder->pos *= 2; - } - else - { - fprintf (stderr, "SoundDecoder_Seek(): couldn't seek %s to %u\n", decoder->filename, seekTime); - break; - } - decoder->error = SOUNDDECODER_OK; - return; - } - case SOUNDDECODER_BUF: - { - uint32 pcm_pos = seekTime * decoder->frequency / 1000; - decoder->pos = pcm_pos * - (decoder->format == decoder_formats.mono16 ? 2 : 4); - //fprintf (stderr, "SoundDecoder_Seek(): %s(buf) (start: %d pos: %d end: %d)\n", - // decoder->filename, decoder->start_sample, pcm_pos, decoder->end_sample); - decoder->error = SOUNDDECODER_OK; - return; - } - case SOUNDDECODER_NULL: - { - uint32 pcm_pos = seekTime * decoder->frequency / 1000; - decoder->pos = pcm_pos * 2; - //fprintf (stderr, "SoundDecoder_Seek(): %s(null) (start: %d pos: %d end: %d)\n", - // decoder->filename, decoder->start_sample, pcm_pos, decoder->end_sample); - decoder->error = SOUNDDECODER_OK; - return; - } - default: - { - fprintf (stderr, "SoundDecoder_Seek(): unknown type %d\n", decoder->type); - break; - } - } - - decoder->error = SOUNDDECODER_ERROR; -} - -void SoundDecoder_Free (TFB_SoundDecoder *decoder) -{ if (!decoder) + return; + if (!decoder->funcs) { + fprintf (stderr, "SoundDecoder_Seek(): bad decoder passed\n"); return; } - switch (decoder->type) + pcm_pos = seekTime * decoder->frequency / 1000; + pcm_pos = decoder->funcs->Seek (decoder, + decoder->start_sample + pcm_pos); + decoder->pos = pcm_pos * decoder->bytes_per_samp; + decoder->error = SOUNDDECODER_OK; +} + +void +SoundDecoder_Free (TFB_SoundDecoder *decoder) +{ + if (!decoder) + return; + if (!decoder->funcs) { - case SOUNDDECODER_WAV: - { - //fprintf (stderr, "SoundDecoder_Free(): freeing %s\n", decoder->filename); - break; - } - case SOUNDDECODER_MOD: - { - MODULE *mod = (MODULE *) decoder->data; - //fprintf (stderr, "SoundDecoder_Free(): freeing %s\n", decoder->filename); - Player_Free (mod); - break; - } - case SOUNDDECODER_OGG: - { - OggVorbis_File *vf = (OggVorbis_File *) decoder->data; - //fprintf (stderr, "SoundDecoder_Free(): freeing %s\n", decoder->filename); - ov_clear (vf); - HFree (vf); - break; - } - case SOUNDDECODER_DUK: - { - DukAud_Track* track = (DukAud_Track*) decoder->data; - //fprintf (stderr, "SoundDecoder_Free(): freeing %s\n", decoder->filename); - duka_closeTrack (track); - break; - } - case SOUNDDECODER_BUF: - break; - case SOUNDDECODER_NULL: - break; - default: - { - fprintf (stderr, "SoundDecoder_Free(): unknown type %d\n", decoder->type); - break; - } + fprintf (stderr, "SoundDecoder_Free(): bad decoder passed\n"); + return; } + decoder->funcs->Close (decoder); + decoder->funcs->Term (decoder); + HFree (decoder->buffer); HFree (decoder->filename); HFree (decoder); } -float SoundDecoder_GetTime (TFB_SoundDecoder *decoder) +float +SoundDecoder_GetTime (TFB_SoundDecoder *decoder) { if (!decoder) + return 0.0f; + if (!decoder->funcs) { + fprintf (stderr, "SoundDecoder_GetTime(): bad decoder passed\n"); return 0.0f; } - switch (decoder->type) - { - case SOUNDDECODER_WAV: - { - //fprintf (stderr, "SoundDecoder_GetTime not supported for wav\n"); - return 0.0f; - } - case SOUNDDECODER_MOD: - { - //fprintf (stderr, "SoundDecoder_GetTime not supported for mod\n"); - return 0.0f; - } - case SOUNDDECODER_OGG: - case SOUNDDECODER_DUK: - case SOUNDDECODER_BUF: - case SOUNDDECODER_NULL: - { - //fprintf (stderr, "SoundDecoder_GetTime not supported for mod\n"); - return ( - (float)( - (decoder->pos >> (decoder->format == decoder_formats.mono16 ? 1 : 2)) - - decoder->start_sample - ) / decoder->frequency); - } - default: - { - fprintf (stderr, "SoundDecoder_GetTime(): unknown type %d\n", decoder->type); - return 0.0f; - } - } + return (float) + ((decoder->pos / decoder->bytes_per_samp) + - decoder->start_sample + ) / decoder->frequency; } uint32 SoundDecoder_GetFrame (TFB_SoundDecoder *decoder) { - uint32 frame = 0; - if (!decoder) return 0; - - switch (decoder->type) + if (!decoder->funcs) { - case SOUNDDECODER_MOD: - { - MODULE *mod = (MODULE *) decoder->data; - frame = mod->sngpos; - break; - } - case SOUNDDECODER_OGG: - { - OggVorbis_File *vf = (OggVorbis_File *) decoder->data; - // this is the closest to a frame there is in ogg vorbis stream - // doesn't seem to be a func to retrive it - frame = vf->os.pageno; - break; - } - case SOUNDDECODER_DUK: - { - DukAud_Track* track = (DukAud_Track*) decoder->data; - frame = duka_getFrame (track); - break; - } - case SOUNDDECODER_WAV: - case SOUNDDECODER_BUF: - case SOUNDDECODER_NULL: - break; - default: - { - fprintf (stderr, "SoundDecoder_GetFrame(): unknown type %d\n", decoder->type); - break; - } + fprintf (stderr, "SoundDecoder_GetFrame(): bad decoder passed\n"); + return 0; } - return frame; + return decoder->funcs->GetFrame (decoder); +} + + +#define THIS_PTR TFB_SoundDecoder* This + +static const char* +bufa_GetName (void) +{ + return "Buffer"; +} + +static bool +bufa_InitModule (int flags) +{ + // this should never be called + fprintf (stderr, "bufa_InitModule(): dead function called\n"); + return false; + + (void)flags; // laugh at compiler warning +} + +static void +bufa_TermModule () +{ + // this should never be called + fprintf (stderr, "bufa_TermModule(): dead function called\n"); +} + +static uint32 +bufa_GetStructSize (void) +{ + return sizeof (TFB_BufSoundDecoder); +} + +static int +bufa_GetError (THIS_PTR) +{ + return 0; // error? what error?! + + (void)This; // laugh at compiler warning +} + +static bool +bufa_Init (THIS_PTR) +{ + TFB_BufSoundDecoder* bufa = (TFB_BufSoundDecoder*) This; + + This->need_swap = false; + // hijack the buffer + bufa->data = This->buffer; + bufa->max_pcm = This->buffer_size / This->bytes_per_samp; + bufa->cur_pcm = bufa->max_pcm; + + return true; +} + +static void +bufa_Term (THIS_PTR) +{ + //TFB_BufSoundDecoder* bufa = (TFB_BufSoundDecoder*) This; + bufa_Close (This); // ensure cleanup +} + +static bool +bufa_Open (THIS_PTR, uio_DirHandle *dir, const char *filename) +{ + // this should never be called + fprintf (stderr, "bufa_Open(): dead function called\n"); + return false; + + // laugh at compiler warnings + (void)This; (void)dir; (void)filename; +} + +static void +bufa_Close (THIS_PTR) +{ + TFB_BufSoundDecoder* bufa = (TFB_BufSoundDecoder*) This; + + // restore the status quo + if (bufa->data) + { + This->buffer = bufa->data; + bufa->data = NULL; + } + bufa->cur_pcm = 0; +} + +static int +bufa_Decode (THIS_PTR, void* buf, sint32 bufsize) +{ + TFB_BufSoundDecoder* bufa = (TFB_BufSoundDecoder*) This; + uint32 dec_pcm; + uint32 dec_bytes; + + dec_pcm = bufsize / This->bytes_per_samp; + if (dec_pcm > bufa->max_pcm - bufa->cur_pcm) + dec_pcm = bufa->max_pcm - bufa->cur_pcm; + dec_bytes = dec_pcm * This->bytes_per_samp; + + // Buffer decode is a hack + This->buffer = (uint8*) bufa->data + + bufa->cur_pcm * This->bytes_per_samp; + + if (dec_pcm > 0) + bufa->cur_pcm += dec_pcm; + + return dec_bytes; + + (void)buf; // laugh at compiler warning +} + +static uint32 +bufa_Seek (THIS_PTR, uint32 pcm_pos) +{ + TFB_BufSoundDecoder* bufa = (TFB_BufSoundDecoder*) This; + + if (pcm_pos > bufa->max_pcm) + pcm_pos = bufa->max_pcm; + bufa->cur_pcm = pcm_pos; + + return pcm_pos; +} + +static uint32 +bufa_GetFrame (THIS_PTR) +{ + return 0; // only 1 frame + + (void)This; // laugh at compiler warning +} + + +static const char* +nula_GetName (void) +{ + return "Null"; +} + +static bool +nula_InitModule (int flags) +{ + // this should never be called + fprintf (stderr, "nula_InitModule(): dead function called\n"); + return false; + + (void)flags; // laugh at compiler warning +} + +static void +nula_TermModule () +{ + // this should never be called + fprintf (stderr, "nula_TermModule(): dead function called\n"); +} + +static uint32 +nula_GetStructSize (void) +{ + return sizeof (TFB_NullSoundDecoder); +} + +static int +nula_GetError (THIS_PTR) +{ + return 0; // error? what error?! + + (void)This; // laugh at compiler warning +} + +static bool +nula_Init (THIS_PTR) +{ + TFB_NullSoundDecoder* nula = (TFB_NullSoundDecoder*) This; + + This->need_swap = false; + nula->cur_pcm = 0; + return true; +} + +static void +nula_Term (THIS_PTR) +{ + //TFB_NullSoundDecoder* nula = (TFB_NullSoundDecoder*) This; + nula_Close (This); // ensure cleanup +} + +static bool +nula_Open (THIS_PTR, uio_DirHandle *dir, const char *filename) +{ + This->frequency = 11025; + This->format = decoder_formats.mono16; + This->is_null = true; + return true; + + // laugh at compiler warnings + (void)dir; (void)filename; +} + +static void +nula_Close (THIS_PTR) +{ + TFB_NullSoundDecoder* nula = (TFB_NullSoundDecoder*) This; + + nula->cur_pcm = 0; +} + +static int +nula_Decode (THIS_PTR, void* buf, sint32 bufsize) +{ + TFB_NullSoundDecoder* nula = (TFB_NullSoundDecoder*) This; + uint32 max_pcm; + uint32 dec_pcm; + uint32 dec_bytes; + + max_pcm = (uint32) (This->length * This->frequency); + dec_pcm = bufsize / This->bytes_per_samp; + if (dec_pcm > max_pcm - nula->cur_pcm) + dec_pcm = max_pcm - nula->cur_pcm; + dec_bytes = dec_pcm * This->bytes_per_samp; + + if (dec_pcm > 0) + { + memset (buf, 0, dec_bytes); + nula->cur_pcm += dec_pcm; + } + + return dec_bytes; +} + +static uint32 +nula_Seek (THIS_PTR, uint32 pcm_pos) +{ + TFB_NullSoundDecoder* nula = (TFB_NullSoundDecoder*) This; + uint32 max_pcm; + + max_pcm = (uint32) (This->length * This->frequency); + if (pcm_pos > max_pcm) + pcm_pos = max_pcm; + nula->cur_pcm = pcm_pos; + + return pcm_pos; +} + +static uint32 +nula_GetFrame (THIS_PTR) +{ + return 0; // only 1 frame + + (void)This; // laugh at compiler warning } diff --git a/sc2/src/sc2code/libs/sound/decoders/decoder.h b/sc2/src/sc2code/libs/sound/decoders/decoder.h index 42885192a..3be8e86d0 100644 --- a/sc2/src/sc2code/libs/sound/decoders/decoder.h +++ b/sc2/src/sc2code/libs/sound/decoders/decoder.h @@ -39,28 +39,61 @@ typedef struct tfb_decoderformats uint32 stereo16; } TFB_DecoderFormats; -typedef struct tfb_sounddecoder +// forward-declare +typedef struct tfb_sounddecoder TFB_SoundDecoder; + +#define THIS_PTR TFB_SoundDecoder* + +typedef struct tfb_sounddecoderfunc { - // public - void *buffer; - uint32 buffer_size; + const char* (* GetName) (void); + bool (* InitModule) (int flags); + void (* TermModule) (); + uint32 (* GetStructSize) (void); + int (* GetError) (THIS_PTR); + bool (* Init) (THIS_PTR); + void (* Term) (THIS_PTR); + bool (* Open) (THIS_PTR, uio_DirHandle *dir, const char *filename); + void (* Close) (THIS_PTR); + int (* Decode) (THIS_PTR, void* buf, sint32 bufsize); + // returns <0 on error, ==0 when no more data, >0 bytes returned + uint32 (* Seek) (THIS_PTR, uint32 pcm_pos); + // returns the pcm position set + uint32 (* GetFrame) (THIS_PTR); + +} TFB_SoundDecoderFuncs; + +#undef THIS_PTR + +struct tfb_sounddecoder +{ + // decoder virtual funcs - R/O + const TFB_SoundDecoderFuncs *funcs; + + // public R/O, set by decoder uint32 format; uint32 frequency; - bool looping; - sint32 error; float length; // total length in seconds - char *decoder_info; + bool is_null; + bool need_swap; + + // public R/O, set by wrapper + void *buffer; + uint32 buffer_size; + sint32 error; + uint32 bytes_per_samp; + + // public R/W + bool looping; // semi-private - sint32 type; uio_DirHandle *dir; char *filename; - void *data; uint32 pos; uint32 start_sample; uint32 end_sample; -} TFB_SoundDecoder; +}; // return values enum @@ -70,18 +103,6 @@ enum SOUNDDECODER_EOF, }; -// types -enum -{ - SOUNDDECODER_NONE, - SOUNDDECODER_WAV, - SOUNDDECODER_MOD, - SOUNDDECODER_OGG, - SOUNDDECODER_NULL, - SOUNDDECODER_BUF, - SOUNDDECODER_DUK, -}; - extern TFB_DecoderFormats decoder_formats; void SoundDecoder_SwapWords (uint16* data, uint32 size); sint32 SoundDecoder_Init (int flags, TFB_DecoderFormats* formats); @@ -92,8 +113,9 @@ uint32 SoundDecoder_Decode (TFB_SoundDecoder *decoder); uint32 SoundDecoder_DecodeAll (TFB_SoundDecoder *decoder); float SoundDecoder_GetTime (TFB_SoundDecoder *decoder); uint32 SoundDecoder_GetFrame (TFB_SoundDecoder *decoder); -void SoundDecoder_Seek (TFB_SoundDecoder *decoder, uint32 pcm_pos); +void SoundDecoder_Seek (TFB_SoundDecoder *decoder, uint32 msecs); void SoundDecoder_Rewind (TFB_SoundDecoder *decoder); void SoundDecoder_Free (TFB_SoundDecoder *decoder); +const char* SoundDecoder_GetName (TFB_SoundDecoder *decoder); #endif diff --git a/sc2/src/sc2code/libs/sound/decoders/dukaud.c b/sc2/src/sc2code/libs/sound/decoders/dukaud.c index f17e4c1a4..11c1bbed6 100644 --- a/sc2/src/sc2code/libs/sound/decoders/dukaud.c +++ b/sc2/src/sc2code/libs/sound/decoders/dukaud.c @@ -21,6 +21,9 @@ #include #include #include "libs/misc.h" +#include "port.h" +#include "types.h" +#include "uio.h" #include "dukaud.h" #include "decoder.h" #include "endian_uqm.h" @@ -28,7 +31,63 @@ #define DATA_BUF_SIZE 0x8000 #define DUCK_GENERAL_FPS 14.622f -static sint32 duka_error = 0; + +#define THIS_PTR TFB_SoundDecoder* This + +static const char* duka_GetName (void); +static bool duka_InitModule (int flags); +static void duka_TermModule (); +static uint32 duka_GetStructSize (void); +static int duka_GetError (THIS_PTR); +static bool duka_Init (THIS_PTR); +static void duka_Term (THIS_PTR); +static bool duka_Open (THIS_PTR, uio_DirHandle *dir, const char *filename); +static void duka_Close (THIS_PTR); +static int duka_Decode (THIS_PTR, void* buf, sint32 bufsize); +static uint32 duka_Seek (THIS_PTR, uint32 pcm_pos); +static uint32 duka_GetFrame (THIS_PTR); + +TFB_SoundDecoderFuncs duka_DecoderVtbl = +{ + duka_GetName, + duka_InitModule, + duka_TermModule, + duka_GetStructSize, + duka_GetError, + duka_Init, + duka_Term, + duka_Open, + duka_Close, + duka_Decode, + duka_Seek, + duka_GetFrame, +}; + +typedef struct tfb_ducksounddecoder +{ + // always the first member + TFB_SoundDecoder decoder; + + // public read-only + uint32 iframe; // current frame index + uint32 cframes; // total count of frames + uint32 channels; // number of channels + uint32 pcm_frame; // samples per frame + + // private + sint32 last_error; + uio_Stream* duk; + uint32* frames; + // buffer + void* data; + uint32 maxdata; + uint32 cbdata; + uint32 dataofs; + // decoder stuff + sint32 predictors[2]; + +} TFB_DuckSoundDecoder; + typedef struct { @@ -45,36 +104,28 @@ typedef struct } DukAud_AudSubframe; sint32 -duka_getError () -{ - sint32 ret = duka_error; - duka_error = dukae_None; - return ret; -} - -sint32 -duka_readAudFrameHeader (DukAud_Track* track, uint32 iframe, +duka_readAudFrameHeader (TFB_DuckSoundDecoder* duka, uint32 iframe, DukAud_AudSubframe* aud) { DukAud_FrameHeader hdr; - uio_fseek (track->duk, track->frames[iframe], SEEK_SET); - if (uio_fread (&hdr, sizeof(hdr), 1, track->duk) != 1) + uio_fseek (duka->duk, duka->frames[iframe], SEEK_SET); + if (uio_fread (&hdr, sizeof(hdr), 1, duka->duk) != 1) { - duka_error = errno; + duka->last_error = errno; return dukae_BadFile; } hdr.audsize = UQM_SwapBE32 (hdr.audsize); - if (uio_fread (aud, sizeof(*aud), 1, track->duk) != 1) + if (uio_fread (aud, sizeof(*aud), 1, duka->duk) != 1) { - duka_error = errno; + duka->last_error = errno; return dukae_BadFile; } aud->magic = UQM_SwapBE16 (aud->magic); if (aud->magic != 0xf77f) - return duka_error = dukae_BadFile; + return duka->last_error = dukae_BadFile; aud->numsamples = UQM_SwapBE16 (aud->numsamples); aud->tag = UQM_SwapBE16 (aud->tag); @@ -84,112 +135,6 @@ duka_readAudFrameHeader (DukAud_Track* track, uint32 iframe, return 0; } -DukAud_Track* -duka_openTrack (uio_DirHandle *dir, const char *file) -{ - DukAud_Track* track; - uio_Stream* duk; - uio_Stream* frm; - DukAud_AudSubframe aud; - char filename[256]; - uint32 filelen; - size_t cread; - uint32 i; - - filelen = strlen (file); - if (filelen > sizeof (filename) - 1) - return NULL; - strcpy (filename, file); - - duk = uio_fopen (dir, filename, "rb"); - if (!duk) - { - duka_error = errno; - return NULL; - } - - strcpy (filename + filelen - 3, "frm"); - frm = uio_fopen (dir, filename, "rb"); - if (!frm) - { - duka_error = errno; - uio_fclose (duk); - return NULL; - } - - track = (DukAud_Track *) HCalloc (sizeof (DukAud_Track)); - track->duk = duk; - - uio_fseek (frm, 0, SEEK_END); - track->cframes = uio_ftell (frm) / sizeof (uint32); - uio_fseek (frm, 0, SEEK_SET); - if (!track->cframes) - { - duka_error = dukae_BadFile; - uio_fclose (frm); - duka_closeTrack (track); - return NULL; - } - - track->frames = (uint32*) HMalloc (track->cframes * sizeof (uint32)); - cread = uio_fread (track->frames, sizeof (uint32), track->cframes, frm); - uio_fclose (frm); - if (cread != track->cframes) - { - duka_error = dukae_BadFile; - duka_closeTrack (track); - return NULL; - } - - for (i = 0; i < track->cframes; ++i) - track->frames[i] = UQM_SwapBE32 (track->frames[i]); - - if (duka_readAudFrameHeader (track, 0, &aud) < 0) - { - duka_closeTrack (track); - return NULL; - } - - track->rate = 22050; - track->channels = 2; - track->pcm_frame = aud.numsamples; - track->data = HMalloc (DATA_BUF_SIZE); - track->maxdata = DATA_BUF_SIZE; - - // estimate - track->length = (float) track->cframes / DUCK_GENERAL_FPS; - - duka_error = 0; - - return track; -} - -void -duka_closeTrack (DukAud_Track* track) -{ - if (track->data) - HFree (track->data); - if (track->duk) - uio_fclose (track->duk); - HFree (track); - duka_error = 0; -} - -bool -duka_seekTrack (DukAud_Track* track, float pos /* in seconds */) -{ - if (pos < 0 || pos > track->length) - return false; - - track->iframe = (uint32) (pos * DUCK_GENERAL_FPS); - track->cbdata = 0; - track->dataofs = 0; - track->predictors[0] = 0; - track->predictors[1] = 0; - - return true; -} - // This table is from one of the files that came with the original 3do source // It's slightly different from the data used by MPlayer. static int adpcm_step[89] = { @@ -300,7 +245,7 @@ decode_nibbles (sint16 *output, sint32 output_size, sint32 channels, // *** END part copied from MPlayer *** sint32 -duka_decodeFrame (DukAud_Track* track, DukAud_AudSubframe* header, +duka_decodeFrame (TFB_DuckSoundDecoder* duka, DukAud_AudSubframe* header, uint8* input) { uint8* inend; @@ -309,7 +254,7 @@ duka_decodeFrame (DukAud_Track* track, DukAud_AudSubframe* header, sint32 outputsize; outputsize = header->numsamples * 2 * sizeof (sint16); - outptr = output = (sint16*) ((uint8*)track->data + track->cbdata); + outptr = output = (sint16*) ((uint8*)duka->data + duka->cbdata); for (inend = input + header->numsamples; input < inend; ++input) { @@ -317,35 +262,35 @@ duka_decodeFrame (DukAud_Track* track, DukAud_AudSubframe* header, *(outptr++) = *input & 0x0f; } - decode_nibbles (output, header->numsamples * 2, track->channels, - track->predictors, header->indices); + decode_nibbles (output, header->numsamples * 2, duka->channels, + duka->predictors, header->indices); - track->cbdata += outputsize; + duka->cbdata += outputsize; return outputsize; } sint32 -duka_readNextFrame (DukAud_Track* track) +duka_readNextFrame (TFB_DuckSoundDecoder* duka) { DukAud_FrameHeader hdr; DukAud_AudSubframe* aud; uint8* p; - uio_fseek (track->duk, track->frames[track->iframe], SEEK_SET); - if (uio_fread (&hdr, sizeof(hdr), 1, track->duk) != 1) + uio_fseek (duka->duk, duka->frames[duka->iframe], SEEK_SET); + if (uio_fread (&hdr, sizeof(hdr), 1, duka->duk) != 1) { - duka_error = errno; + duka->last_error = errno; return dukae_BadFile; } hdr.audsize = UQM_SwapBE32 (hdr.audsize); // dump encoded data at the end of the buffer aligned on 8-byte - p = ((uint8*)track->data + track->maxdata - ((hdr.audsize + 7) & (-8))); - if (uio_fread (p, 1, hdr.audsize, track->duk) != hdr.audsize) + p = ((uint8*)duka->data + duka->maxdata - ((hdr.audsize + 7) & (-8))); + if (uio_fread (p, 1, hdr.audsize, duka->duk) != hdr.audsize) { - duka_error = errno; + duka->last_error = errno; return dukae_BadFile; } aud = (DukAud_AudSubframe*) p; @@ -353,76 +298,247 @@ duka_readNextFrame (DukAud_Track* track) aud->magic = UQM_SwapBE16 (aud->magic); if (aud->magic != 0xf77f) - return duka_error = dukae_BadFile; + return duka->last_error = dukae_BadFile; aud->numsamples = UQM_SwapBE16 (aud->numsamples); aud->tag = UQM_SwapBE16 (aud->tag); aud->indices[0] = UQM_SwapBE16 (aud->indices[0]); aud->indices[1] = UQM_SwapBE16 (aud->indices[1]); - track->iframe++; + duka->iframe++; - return duka_decodeFrame (track, aud, p); + return duka_decodeFrame (duka, aud, p); } static sint32 -duka_stuffBuffer (DukAud_Track* track, void* buf, sint32 bufsize) +duka_stuffBuffer (TFB_DuckSoundDecoder* duka, void* buf, sint32 bufsize) { sint32 dataleft; - dataleft = track->cbdata - track->dataofs; + dataleft = duka->cbdata - duka->dataofs; if (dataleft > 0) { if (dataleft > bufsize) dataleft = bufsize & (-4); - memcpy (buf, (uint8*)track->data + track->dataofs, dataleft); - track->dataofs += dataleft; + memcpy (buf, (uint8*)duka->data + duka->dataofs, dataleft); + duka->dataofs += dataleft; } - if (track->cbdata > 0 && track->dataofs >= track->cbdata) - track->cbdata = track->dataofs = 0; // reset for new data + if (duka->cbdata > 0 && duka->dataofs >= duka->cbdata) + duka->cbdata = duka->dataofs = 0; // reset for new data return dataleft; } -sint32 -duka_readData (DukAud_Track* track, void* buf, sint32 bufsize) + +static const char* +duka_GetName (void) { + return "DukAud"; +} + +static bool +duka_InitModule (int flags) +{ + // no specific module init + return true; + + (void)flags; // laugh at compiler warning +} + +static void +duka_TermModule () +{ + // no specific module term +} + +static uint32 +duka_GetStructSize (void) +{ + return sizeof (TFB_DuckSoundDecoder); +} + +static int +duka_GetError (THIS_PTR) +{ + TFB_DuckSoundDecoder* duka = (TFB_DuckSoundDecoder*) This; + int ret = duka->last_error; + duka->last_error = dukae_None; + return ret; +} + +static bool +duka_Init (THIS_PTR) +{ + //TFB_DuckSoundDecoder* duka = (TFB_DuckSoundDecoder*) This; + This->need_swap = + decoder_formats.big_endian != decoder_formats.want_big_endian; + return true; +} + +static void +duka_Term (THIS_PTR) +{ + //TFB_DuckSoundDecoder* duka = (TFB_DuckSoundDecoder*) This; + duka_Close (This); // ensure cleanup +} + +static bool +duka_Open (THIS_PTR, uio_DirHandle *dir, const char *file) +{ + TFB_DuckSoundDecoder* duka = (TFB_DuckSoundDecoder*) This; + uio_Stream* duk; + uio_Stream* frm; + DukAud_AudSubframe aud; + char filename[256]; + uint32 filelen; + size_t cread; + uint32 i; + + filelen = strlen (file); + if (filelen > sizeof (filename) - 1) + return false; + strcpy (filename, file); + + duk = uio_fopen (dir, filename, "rb"); + if (!duk) + { + duka->last_error = errno; + return false; + } + + strcpy (filename + filelen - 3, "frm"); + frm = uio_fopen (dir, filename, "rb"); + if (!frm) + { + duka->last_error = errno; + uio_fclose (duk); + return false; + } + + duka->duk = duk; + + uio_fseek (frm, 0, SEEK_END); + duka->cframes = uio_ftell (frm) / sizeof (uint32); + uio_fseek (frm, 0, SEEK_SET); + if (!duka->cframes) + { + duka->last_error = dukae_BadFile; + uio_fclose (frm); + duka_Close (This); + return false; + } + + duka->frames = (uint32*) HMalloc (duka->cframes * sizeof (uint32)); + cread = uio_fread (duka->frames, sizeof (uint32), duka->cframes, frm); + uio_fclose (frm); + if (cread != duka->cframes) + { + duka->last_error = dukae_BadFile; + duka_Close (This); + return false; + } + + for (i = 0; i < duka->cframes; ++i) + duka->frames[i] = UQM_SwapBE32 (duka->frames[i]); + + if (duka_readAudFrameHeader (duka, 0, &aud) < 0) + { + duka_Close (This); + return false; + } + + This->frequency = 22050; + This->format = decoder_formats.stereo16; + duka->channels = 2; + duka->pcm_frame = aud.numsamples; + duka->data = HMalloc (DATA_BUF_SIZE); + duka->maxdata = DATA_BUF_SIZE; + + // estimate + This->length = (float) duka->cframes / DUCK_GENERAL_FPS; + + duka->last_error = 0; + + return true; +} + +static void +duka_Close (THIS_PTR) +{ + TFB_DuckSoundDecoder* duka = (TFB_DuckSoundDecoder*) This; + + if (duka->data) + { + HFree (duka->data); + duka->data = NULL; + } + if (duka->frames) + { + HFree (duka->frames); + duka->frames = NULL; + } + if (duka->duk) + { + uio_fclose (duka->duk); + duka->duk = NULL; + } + duka->last_error = 0; +} + +static int +duka_Decode (THIS_PTR, void* buf, sint32 bufsize) +{ + TFB_DuckSoundDecoder* duka = (TFB_DuckSoundDecoder*) This; sint32 stuffed; sint32 total = 0; if (bufsize <= 0) - return duka_error = dukae_BadArg; + return duka->last_error = dukae_BadArg; do { - stuffed = duka_stuffBuffer (track, buf, bufsize); + stuffed = duka_stuffBuffer (duka, buf, bufsize); ((uint8*)buf) += stuffed; bufsize -= stuffed; total += stuffed; - if (bufsize > 0 && track->iframe < track->cframes) + if (bufsize > 0 && duka->iframe < duka->cframes) { - stuffed = duka_readNextFrame (track); + stuffed = duka_readNextFrame (duka); if (stuffed <= 0) return stuffed; } - } while (bufsize > 0 && track->iframe < track->cframes); + } while (bufsize > 0 && duka->iframe < duka->cframes); return total; } -uint32 -duka_getFrame (DukAud_Track* track) +static uint32 +duka_Seek (THIS_PTR, uint32 pcm_pos) { - // if there is nothing buffered return the actual current frame - // otherwise return previous - return track->dataofs == track->cbdata ? - track->iframe : track->iframe - 1; + TFB_DuckSoundDecoder* duka = (TFB_DuckSoundDecoder*) This; + uint32 iframe; + + iframe = pcm_pos / duka->pcm_frame; + if (iframe < duka->cframes) + { + duka->iframe = iframe; + duka->cbdata = 0; + duka->dataofs = 0; + duka->predictors[0] = 0; + duka->predictors[1] = 0; + } + return duka->iframe * duka->pcm_frame; } -uint32 -duka_getFrameSize (DukAud_Track* track) +static uint32 +duka_GetFrame (THIS_PTR) { - return track->pcm_frame * track->channels * sizeof (uint16); + TFB_DuckSoundDecoder* duka = (TFB_DuckSoundDecoder*) This; + + // if there is nothing buffered return the actual current frame + // otherwise return previous + return duka->dataofs == duka->cbdata ? + duka->iframe : duka->iframe - 1; } diff --git a/sc2/src/sc2code/libs/sound/decoders/dukaud.h b/sc2/src/sc2code/libs/sound/decoders/dukaud.h index c598199b8..23c420126 100644 --- a/sc2/src/sc2code/libs/sound/decoders/dukaud.h +++ b/sc2/src/sc2code/libs/sound/decoders/dukaud.h @@ -19,32 +19,9 @@ #ifndef DUKAUD_H #define DUKAUD_H -#include "port.h" -#include "types.h" -#include "uio.h" +#include "decoder.h" -typedef struct -{ - // public read-only - uint32 iframe; // current frame index - uint32 cframes; // total count of frames - uint32 rate; // frequency - uint32 channels; // number of channels - uint32 pcm_frame; // samples per frame - float length; // length in seconds (estimated) - - // private - uio_Stream* duk; - uint32* frames; - // buffer - void* data; - uint32 maxdata; - uint32 cbdata; - uint32 dataofs; - // decoder stuff - sint32 predictors[2]; - -} DukAud_Track; +extern TFB_SoundDecoderFuncs duka_DecoderVtbl; typedef enum { @@ -56,12 +33,4 @@ typedef enum dukae_Other = -1000, } DukAud_Error; -sint32 duka_getError (); -DukAud_Track* duka_openTrack (uio_DirHandle *dir, const char *file); -void duka_closeTrack (DukAud_Track* track); -bool duka_seekTrack (DukAud_Track* track, float pos /* in seconds */); -sint32 duka_readData (DukAud_Track* track, void* buf, sint32 bufsize); -uint32 duka_getFrame (DukAud_Track* track); -uint32 duka_getFrameSize (DukAud_Track* track); - #endif // DUKAUD_H diff --git a/sc2/src/sc2code/libs/sound/decoders/modaud.c b/sc2/src/sc2code/libs/sound/decoders/modaud.c new file mode 100644 index 000000000..2f437a236 --- /dev/null +++ b/sc2/src/sc2code/libs/sound/decoders/modaud.c @@ -0,0 +1,228 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* MikMod decoder (.mod adapter) + */ + +#include +#include +#include +#include "libs/misc.h" +#include "port.h" +#include "types.h" +#include "uio.h" +#include "decoder.h" +#include "mikmod/mikmod.h" +#include "libs/sound/sound_common.h" +#include "modaud.h" + +#define THIS_PTR TFB_SoundDecoder* This + +static const char* moda_GetName (void); +static bool moda_InitModule (int flags); +static void moda_TermModule (); +static uint32 moda_GetStructSize (void); +static int moda_GetError (THIS_PTR); +static bool moda_Init (THIS_PTR); +static void moda_Term (THIS_PTR); +static bool moda_Open (THIS_PTR, uio_DirHandle *dir, const char *filename); +static void moda_Close (THIS_PTR); +static int moda_Decode (THIS_PTR, void* buf, sint32 bufsize); +static uint32 moda_Seek (THIS_PTR, uint32 pcm_pos); +static uint32 moda_GetFrame (THIS_PTR); + +TFB_SoundDecoderFuncs moda_DecoderVtbl = +{ + moda_GetName, + moda_InitModule, + moda_TermModule, + moda_GetStructSize, + moda_GetError, + moda_Init, + moda_Term, + moda_Open, + moda_Close, + moda_Decode, + moda_Seek, + moda_GetFrame, +}; + +typedef struct tfb_modsounddecoder +{ + // always the first member + TFB_SoundDecoder decoder; + + // private + sint32 last_error; + MODULE* module; + +} TFB_ModSoundDecoder; + +MIKMODAPI extern struct MDRIVER drv_openal; + + +static const char* +moda_GetName (void) +{ + return "MikMod"; +} + +static bool +moda_InitModule (int flags) +{ + MikMod_RegisterDriver (&drv_openal); + MikMod_RegisterAllLoaders (); + + if (flags & TFB_SOUNDFLAGS_HQAUDIO) + { + md_mode = DMODE_HQMIXER|DMODE_STEREO|DMODE_16BITS|DMODE_INTERP|DMODE_SURROUND; + md_mixfreq = 44100; + md_reverb = 1; + } + else if (flags & TFB_SOUNDFLAGS_LQAUDIO) + { + md_mode = DMODE_SOFT_MUSIC|DMODE_STEREO|DMODE_16BITS; + md_mixfreq = 22050; + md_reverb = 0; + } + else + { + md_mode = DMODE_SOFT_MUSIC|DMODE_STEREO|DMODE_16BITS|DMODE_INTERP; + md_mixfreq = 44100; + md_reverb = 0; + } + + md_pansep = 64; + + if (MikMod_Init ("")) + { + fprintf (stderr, "MikMod_Init() failed, %s\n", + MikMod_strerror (MikMod_errno)); + return false; + } + + return true; +} + +static void +moda_TermModule () +{ + MikMod_Exit (); +} + +static uint32 +moda_GetStructSize (void) +{ + return sizeof (TFB_ModSoundDecoder); +} + +static int +moda_GetError (THIS_PTR) +{ + TFB_ModSoundDecoder* moda = (TFB_ModSoundDecoder*) This; + int ret = moda->last_error; + moda->last_error = 0; + return ret; +} + +static bool +moda_Init (THIS_PTR) +{ + //TFB_ModSoundDecoder* moda = (TFB_ModSoundDecoder*) This; + This->need_swap = + decoder_formats.big_endian != decoder_formats.want_big_endian; + return true; +} + +static void +moda_Term (THIS_PTR) +{ + //TFB_ModSoundDecoder* moda = (TFB_ModSoundDecoder*) This; + moda_Close (This); // ensure cleanup +} + +static bool +moda_Open (THIS_PTR, uio_DirHandle *dir, const char *filename) +{ + TFB_ModSoundDecoder* moda = (TFB_ModSoundDecoder*) This; + MODULE* mod; + + mod = Player_Load (dir, (char*) filename, 4, 0); + if (!mod) + { + fprintf (stderr, "moda_Open(): could not load %s\n", filename); + return false; + } + + moda->module = mod; + mod->extspd = 1; + mod->panflag = 1; + mod->wrap = 0; + mod->loop = 1; + + This->format = decoder_formats.stereo16; + This->frequency = md_mixfreq; + This->length = 0; // FIXME way to obtain this from mikmod? + + moda->last_error = 0; + + return true; +} + +static void +moda_Close (THIS_PTR) +{ + TFB_ModSoundDecoder* moda = (TFB_ModSoundDecoder*) This; + + if (moda->module) + { + Player_Free (moda->module); + moda->module = NULL; + } +} + +static int +moda_Decode (THIS_PTR, void* buf, sint32 bufsize) +{ + TFB_ModSoundDecoder* moda = (TFB_ModSoundDecoder*) This; + + Player_Start (moda->module); + if (!Player_Active()) + return 0; + + return VC_WriteBytes (buf, bufsize); +} + +static uint32 +moda_Seek (THIS_PTR, uint32 pcm_pos) +{ + TFB_ModSoundDecoder* moda = (TFB_ModSoundDecoder*) This; + + Player_Start (moda->module); + if (pcm_pos) + fprintf (stderr, "moda_Seek(): " + "non-zero seek positions not supported for mod\n"); + Player_SetPosition (0); + + return 0; +} + +static uint32 +moda_GetFrame (THIS_PTR) +{ + TFB_ModSoundDecoder* moda = (TFB_ModSoundDecoder*) This; + return moda->module->sngpos; +} diff --git a/sc2/src/sc2code/libs/sound/decoders/modaud.h b/sc2/src/sc2code/libs/sound/decoders/modaud.h new file mode 100644 index 000000000..3b0eb8650 --- /dev/null +++ b/sc2/src/sc2code/libs/sound/decoders/modaud.h @@ -0,0 +1,26 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* MikMod adapter */ + +#ifndef MODAUD_H +#define MODAUD_H + +#include "decoder.h" + +extern TFB_SoundDecoderFuncs moda_DecoderVtbl; + +#endif // MODAUD_H diff --git a/sc2/src/sc2code/libs/sound/decoders/oggaud.c b/sc2/src/sc2code/libs/sound/decoders/oggaud.c new file mode 100644 index 000000000..01dfe6018 --- /dev/null +++ b/sc2/src/sc2code/libs/sound/decoders/oggaud.c @@ -0,0 +1,256 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* Ogg Vorbis decoder (.ogg adapter) + */ + +#include +#include +#include +#include "libs/misc.h" +#include "port.h" +#include "types.h" +#include "uio.h" +#include "decoder.h" +#include +#include +#include "oggaud.h" + + +#define THIS_PTR TFB_SoundDecoder* This + +static const char* ova_GetName (void); +static bool ova_InitModule (int flags); +static void ova_TermModule (); +static uint32 ova_GetStructSize (void); +static int ova_GetError (THIS_PTR); +static bool ova_Init (THIS_PTR); +static void ova_Term (THIS_PTR); +static bool ova_Open (THIS_PTR, uio_DirHandle *dir, const char *filename); +static void ova_Close (THIS_PTR); +static int ova_Decode (THIS_PTR, void* buf, sint32 bufsize); +static uint32 ova_Seek (THIS_PTR, uint32 pcm_pos); +static uint32 ova_GetFrame (THIS_PTR); + +TFB_SoundDecoderFuncs ova_DecoderVtbl = +{ + ova_GetName, + ova_InitModule, + ova_TermModule, + ova_GetStructSize, + ova_GetError, + ova_Init, + ova_Term, + ova_Open, + ova_Close, + ova_Decode, + ova_Seek, + ova_GetFrame, +}; + +typedef struct tfb_oggsounddecoder +{ + // always the first member + TFB_SoundDecoder decoder; + + // private + sint32 last_error; + OggVorbis_File vf; + +} TFB_OggSoundDecoder; + +static size_t +ogg_read (void *ptr, size_t size, size_t nmemb, void *datasource) +{ + return uio_fread (ptr, size, nmemb, (uio_Stream *) datasource); +} + +static int +ogg_seek (void *datasource, ogg_int64_t offset, int whence) +{ + long off = (long) offset; + return uio_fseek ((uio_Stream *) datasource, off, whence); +} + +static int +ogg_close (void *datasource) +{ + return uio_fclose ((uio_Stream *) datasource); +} + +static long +ogg_tell (void *datasource) +{ + return uio_ftell ((uio_Stream *) datasource); +} + +static const ov_callbacks ogg_callbacks = +{ + ogg_read, + ogg_seek, + ogg_close, + ogg_tell, +}; + +static const char* +ova_GetName (void) +{ + return "Ogg Vorbis"; +} + +static bool +ova_InitModule (int flags) +{ + // no specific module init + return true; + + (void)flags; // laugh at compiler warning +} + +static void +ova_TermModule () +{ + // no specific module term +} + +static uint32 +ova_GetStructSize (void) +{ + return sizeof (TFB_OggSoundDecoder); +} + +static int +ova_GetError (THIS_PTR) +{ + TFB_OggSoundDecoder* ova = (TFB_OggSoundDecoder*) This; + int ret = ova->last_error; + ova->last_error = 0; + return ret; +} + +static bool +ova_Init (THIS_PTR) +{ + //TFB_OggSoundDecoder* ova = (TFB_OggSoundDecoder*) This; + This->need_swap = false; + return true; +} + +static void +ova_Term (THIS_PTR) +{ + //TFB_OggSoundDecoder* ova = (TFB_OggSoundDecoder*) This; + ova_Close (This); // ensure cleanup +} + +static bool +ova_Open (THIS_PTR, uio_DirHandle *dir, const char *filename) +{ + TFB_OggSoundDecoder* ova = (TFB_OggSoundDecoder*) This; + int rc; + uio_Stream *fp; + vorbis_info *vinfo; + + fp = uio_fopen (dir, filename, "rb"); + if (fp == NULL) + { + fprintf (stderr, "ova_Open(): could not open %s\n", filename); + return false; + } + + rc = ov_open_callbacks (fp, &ova->vf, NULL, 0, ogg_callbacks); + if (rc != 0) + { + fprintf (stderr, "ova_Open(): " + "ov_open_callbacks failed for %s, error code %d\n", + filename, rc); + uio_fclose (fp); + return false; + } + + vinfo = ov_info (&ova->vf, -1); + if (!vinfo) + { + fprintf (stderr, "ova_Open(): " + "failed to retrieve ogg bitstream info for %s\n", + filename); + ov_clear (&ova->vf); + return false; + } + + This->frequency = vinfo->rate; + This->length = (float) ov_time_total (&ova->vf, -1); + + if (vinfo->channels == 1) + This->format = decoder_formats.mono16; + else + This->format = decoder_formats.stereo16; + + ova->last_error = 0; + + return true; +} + +static void +ova_Close (THIS_PTR) +{ + TFB_OggSoundDecoder* ova = (TFB_OggSoundDecoder*) This; + + ov_clear (&ova->vf); +} + +static int +ova_Decode (THIS_PTR, void* buf, sint32 bufsize) +{ + TFB_OggSoundDecoder* ova = (TFB_OggSoundDecoder*) This; + long rc; + int bitstream; + + rc = ov_read (&ova->vf, buf, bufsize, decoder_formats.want_big_endian, + 2, 1, &bitstream); + + if (rc < 0) + ova->last_error = rc; + else + ova->last_error = 0; + + return rc; +} + +static uint32 +ova_Seek (THIS_PTR, uint32 pcm_pos) +{ + TFB_OggSoundDecoder* ova = (TFB_OggSoundDecoder*) This; + int ret; + + ret = ov_pcm_seek (&ova->vf, pcm_pos); + if (ret != 0) + { + ova->last_error = ret; + return (uint32) ov_pcm_tell (&ova->vf); + } + else + return pcm_pos; +} + +static uint32 +ova_GetFrame (THIS_PTR) +{ + TFB_OggSoundDecoder* ova = (TFB_OggSoundDecoder*) This; + // this is the closest to a frame there is in ogg vorbis stream + // doesn't seem to be a func to retrive it + return ova->vf.os.pageno; +} diff --git a/sc2/src/sc2code/libs/sound/decoders/oggaud.h b/sc2/src/sc2code/libs/sound/decoders/oggaud.h new file mode 100644 index 000000000..4e443c47d --- /dev/null +++ b/sc2/src/sc2code/libs/sound/decoders/oggaud.h @@ -0,0 +1,26 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* Ogg Vorbis adapter */ + +#ifndef OGGAUD_H +#define OGGAUD_H + +#include "decoder.h" + +extern TFB_SoundDecoderFuncs ova_DecoderVtbl; + +#endif // OGGAUD_H diff --git a/sc2/src/sc2code/libs/sound/decoders/wav.c b/sc2/src/sc2code/libs/sound/decoders/wav.c index fffeae2c7..ece73f6eb 100644 --- a/sc2/src/sc2code/libs/sound/decoders/wav.c +++ b/sc2/src/sc2code/libs/sound/decoders/wav.c @@ -14,17 +14,22 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* Loader for .wav files +/* Wave decoder (.wav adapter) * Code is based on Creative's Win32 OpenAL implementation. */ #include +#include #include +#include "port.h" +#include "types.h" +#include "uio.h" +#include "endian_uqm.h" #include "libs/misc.h" #include "wav.h" -#include "decoder.h" -#include "endian_uqm.h" +#define RIFF 0x46464952 /* "RIFF" */ +#define WAVE 0x45564157 /* "WAVE" */ #define FMT 0x20746D66 /* "fmt " */ #define DATA 0x61746164 /* "data" */ @@ -52,100 +57,304 @@ typedef struct } WAVChunkHdr_Struct; -void -LoadWAVFile (uio_DirHandle *dir, const char *file, uint32 *format, - void **data, uint32 *size, uint32 *freq, bool want_big_endian) +#define THIS_PTR TFB_SoundDecoder* This + +static const char* wava_GetName (void); +static bool wava_InitModule (int flags); +static void wava_TermModule (); +static uint32 wava_GetStructSize (void); +static int wava_GetError (THIS_PTR); +static bool wava_Init (THIS_PTR); +static void wava_Term (THIS_PTR); +static bool wava_Open (THIS_PTR, uio_DirHandle *dir, const char *filename); +static void wava_Close (THIS_PTR); +static int wava_Decode (THIS_PTR, void* buf, sint32 bufsize); +static uint32 wava_Seek (THIS_PTR, uint32 pcm_pos); +static uint32 wava_GetFrame (THIS_PTR); + +TFB_SoundDecoderFuncs wava_DecoderVtbl = { - WAVChunkHdr_Struct ChunkHdr; - WAVFileHdr_Struct FileHdr; - WAVFmtHdr_Struct FmtHdr; + wava_GetName, + wava_InitModule, + wava_TermModule, + wava_GetStructSize, + wava_GetError, + wava_Init, + wava_Term, + wava_Open, + wava_Close, + wava_Decode, + wava_Seek, + wava_GetFrame, +}; + +typedef struct tfb_wavesounddecoder +{ + // always the first member + TFB_SoundDecoder decoder; + + // private + sint32 last_error; uio_Stream *fp; - - *format = decoder_formats.mono16; - *data = NULL; - *size = 0; - *freq = 22050; - - fp = uio_fopen (dir, file, "rb"); - if (fp) - { - uio_fread(&FileHdr.Id, 4, 1, fp); - FileHdr.Id = UQM_SwapLE32 (FileHdr.Id); - uio_fread(&FileHdr.Size, 4, 1, fp); - FileHdr.Size = UQM_SwapLE32 (FileHdr.Size); - uio_fread(&FileHdr.Type, 4, 1, fp); - FileHdr.Type = UQM_SwapLE32 (FileHdr.Type); + WAVFmtHdr_Struct FmtHdr; + uint32 data_ofs; + uint32 data_size; + uint32 max_pcm; + uint32 cur_pcm; - FileHdr.Size = ((FileHdr.Size + 1) & ~1) - 4; - while (FileHdr.Size != 0) - { - if (!uio_fread (&ChunkHdr.Id, 4, 1, fp)) - break; - ChunkHdr.Id = UQM_SwapLE32 (ChunkHdr.Id); - if (!uio_fread (&ChunkHdr.Size, 4, 1, fp)) - break; - ChunkHdr.Size = UQM_SwapLE32 (ChunkHdr.Size); +} TFB_WaveSoundDecoder; - if (ChunkHdr.Id == FMT) - { - uio_fread (&FmtHdr.Format, 2, 1, fp); - FmtHdr.Format = UQM_SwapLE16 (FmtHdr.Format); - uio_fread (&FmtHdr.Channels, 2, 1, fp); - FmtHdr.Channels = UQM_SwapLE16 (FmtHdr.Channels); - uio_fread (&FmtHdr.SamplesPerSec, 4, 1, fp); - FmtHdr.SamplesPerSec = UQM_SwapLE32 (FmtHdr.SamplesPerSec); - uio_fread (&FmtHdr.BytesPerSec, 4, 1, fp); - FmtHdr.BytesPerSec = UQM_SwapLE32 (FmtHdr.BytesPerSec); - uio_fread (&FmtHdr.BlockAlign, 2, 1, fp); - FmtHdr.BlockAlign = UQM_SwapLE16 (FmtHdr.BlockAlign); - uio_fread (&FmtHdr.BitsPerSample, 2, 1, fp); - FmtHdr.BitsPerSample = UQM_SwapLE16 (FmtHdr.BitsPerSample); - if (FmtHdr.Format == 0x0001) - { - *format=(FmtHdr.Channels == 1 ? - (FmtHdr.BitsPerSample == 8 ? - decoder_formats.mono8 - : decoder_formats.mono16) - : (FmtHdr.BitsPerSample == 8 ? - decoder_formats.stereo8 - : decoder_formats.stereo16) - ); - *freq = FmtHdr.SamplesPerSec; - uio_fseek (fp, ChunkHdr.Size - 16, SEEK_CUR); - } - else - { - fprintf (stderr, "LoadWAVFile(): unsupported format %x\n", FmtHdr.Format); - uio_fclose (fp); - return; - } - } - else if (ChunkHdr.Id == DATA) - { - *size = ChunkHdr.Size; - if ((*data = HMalloc (ChunkHdr.Size + 31))) - uio_fread (*data, FmtHdr.BlockAlign, ChunkHdr.Size / FmtHdr.BlockAlign, fp); - memset(((char *)*data) + ChunkHdr.Size, 0, 31); - } - else - { - uio_fseek(fp, ChunkHdr.Size, SEEK_CUR); - } - - uio_fseek (fp, ChunkHdr.Size & 1, SEEK_CUR); - FileHdr.Size -= (((ChunkHdr.Size + 1) & ~1) + 8); - } - uio_fclose(fp); - } - - if (want_big_endian && - (*format == decoder_formats.stereo16 || *format == decoder_formats.mono16)) - { - SoundDecoder_SwapWords (*data, *size); - } - - if (*size == 0) - fprintf (stderr, "LoadWAVFile(): loading %s failed!\n", file); +static const char* +wava_GetName (void) +{ + return "Wave"; } +static bool +wava_InitModule (int flags) +{ + // no specific module init + return true; + + (void)flags; // laugh at compiler warning +} + +static void +wava_TermModule () +{ + // no specific module term +} + +static uint32 +wava_GetStructSize (void) +{ + return sizeof (TFB_WaveSoundDecoder); +} + +static int +wava_GetError (THIS_PTR) +{ + TFB_WaveSoundDecoder* wava = (TFB_WaveSoundDecoder*) This; + int ret = wava->last_error; + wava->last_error = 0; + return ret; +} + +static bool +wava_Init (THIS_PTR) +{ + //TFB_WaveSoundDecoder* wava = (TFB_WaveSoundDecoder*) This; + This->need_swap = decoder_formats.want_big_endian; + return true; +} + +static void +wava_Term (THIS_PTR) +{ + //TFB_WaveSoundDecoder* wava = (TFB_WaveSoundDecoder*) This; + wava_Close (This); // ensure cleanup +} + +static bool +wava_readFileHeader (TFB_WaveSoundDecoder* wava, WAVFileHdr_Struct* hdr) +{ + if (!uio_fread (&hdr->Id, 4, 1, wava->fp) || + !uio_fread (&hdr->Size, 4, 1, wava->fp) || + !uio_fread (&hdr->Type, 4, 1, wava->fp)) + { + wava->last_error = errno; + return false; + } + hdr->Id = UQM_SwapLE32 (hdr->Id); + hdr->Size = UQM_SwapLE32 (hdr->Size); + hdr->Type = UQM_SwapLE32 (hdr->Type); + + return true; +} + +static bool +wava_readChunkHeader (TFB_WaveSoundDecoder* wava, WAVChunkHdr_Struct* chunk) +{ + if (!uio_fread (&chunk->Id, 4, 1, wava->fp) || + !uio_fread (&chunk->Size, 4, 1, wava->fp)) + return false; + + chunk->Id = UQM_SwapLE32 (chunk->Id); + chunk->Size = UQM_SwapLE32 (chunk->Size); + + return true; +} + +static bool +wava_readFormatHeader (TFB_WaveSoundDecoder* wava, WAVFmtHdr_Struct* fmt) +{ + if (!uio_fread (&fmt->Format, 2, 1, wava->fp) || + !uio_fread (&fmt->Channels, 2, 1, wava->fp) || + !uio_fread (&fmt->SamplesPerSec, 4, 1, wava->fp) || + !uio_fread (&fmt->BytesPerSec, 4, 1, wava->fp) || + !uio_fread (&fmt->BlockAlign, 2, 1, wava->fp) || + !uio_fread (&fmt->BitsPerSample, 2, 1, wava->fp)) + return false; + + fmt->Format = UQM_SwapLE16 (fmt->Format); + fmt->Channels = UQM_SwapLE16 (fmt->Channels); + fmt->SamplesPerSec = UQM_SwapLE32 (fmt->SamplesPerSec); + fmt->BytesPerSec = UQM_SwapLE32 (fmt->BytesPerSec); + fmt->BlockAlign = UQM_SwapLE16 (fmt->BlockAlign); + fmt->BitsPerSample = UQM_SwapLE16 (fmt->BitsPerSample); + + return true; +} + +static bool +wava_Open (THIS_PTR, uio_DirHandle *dir, const char *filename) +{ + TFB_WaveSoundDecoder* wava = (TFB_WaveSoundDecoder*) This; + WAVFileHdr_Struct FileHdr; + WAVChunkHdr_Struct ChunkHdr; + + wava->fp = uio_fopen (dir, filename, "rb"); + if (!wava->fp) + { + wava->last_error = errno; + return false; + } + + wava->data_size = 0; + wava->data_ofs = 0; + + // read wave header + if (!wava_readFileHeader (wava, &FileHdr)) + { + wava->last_error = errno; + wava_Close (This); + return false; + } + if (FileHdr.Id != RIFF || FileHdr.Type != WAVE) + { + fprintf (stderr, "wava_Open(): " + "not a wave file, ID 0x%08x, Type 0x%08x\n", + FileHdr.Id, FileHdr.Type); + wava_Close (This); + return false; + } + + for (FileHdr.Size = ((FileHdr.Size + 1) & ~1) - 4; FileHdr.Size != 0; + FileHdr.Size -= (((ChunkHdr.Size + 1) & ~1) + 8)) + { + if (!wava_readChunkHeader (wava, &ChunkHdr)) + { + wava->last_error = errno; + wava_Close (This); + return false; + } + + if (ChunkHdr.Id == FMT) + { + if (!wava_readFormatHeader (wava, &wava->FmtHdr)) + { + wava->last_error = errno; + wava_Close (This); + return false; + } + uio_fseek (wava->fp, ChunkHdr.Size - 16, SEEK_CUR); + } + else + { + if (ChunkHdr.Id == DATA) + { + wava->data_size = ChunkHdr.Size; + wava->data_ofs = uio_ftell (wava->fp); + } + uio_fseek (wava->fp, ChunkHdr.Size, SEEK_CUR); + } + + uio_fseek (wava->fp, ChunkHdr.Size & 1, SEEK_CUR); + } + + if (!wava->data_size || !wava->data_ofs) + { + fprintf (stderr, "wava_Open(): bad wave file, no DATA chunk found\n"); + wava_Close (This); + return false; + } + + if (wava->FmtHdr.Format == 0x0001) + { + This->format = (wava->FmtHdr.Channels == 1 ? + (wava->FmtHdr.BitsPerSample == 8 ? + decoder_formats.mono8 : decoder_formats.mono16) + : + (wava->FmtHdr.BitsPerSample == 8 ? + decoder_formats.stereo8 : decoder_formats.stereo16) + ); + This->frequency = wava->FmtHdr.SamplesPerSec; + } + else + { + fprintf (stderr, "wava_Open(): unsupported format %x\n", wava->FmtHdr.Format); + wava_Close (This); + return false; + } + + uio_fseek (wava->fp, wava->data_ofs, SEEK_SET); + wava->max_pcm = wava->data_size / wava->FmtHdr.BlockAlign; + wava->cur_pcm = 0; + This->length = (float) wava->max_pcm / wava->FmtHdr.SamplesPerSec; + wava->last_error = 0; + + return true; +} + +static void +wava_Close (THIS_PTR) +{ + TFB_WaveSoundDecoder* wava = (TFB_WaveSoundDecoder*) This; + + if (wava->fp) + { + uio_fclose (wava->fp); + wava->fp = NULL; + } +} + +static int +wava_Decode (THIS_PTR, void* buf, sint32 bufsize) +{ + TFB_WaveSoundDecoder* wava = (TFB_WaveSoundDecoder*) This; + uint32 dec_pcm; + + dec_pcm = bufsize / wava->FmtHdr.BlockAlign; + if (dec_pcm > wava->max_pcm - wava->cur_pcm) + dec_pcm = wava->max_pcm - wava->cur_pcm; + + dec_pcm = uio_fread (buf, wava->FmtHdr.BlockAlign, dec_pcm, wava->fp); + wava->cur_pcm += dec_pcm; + + return dec_pcm * wava->FmtHdr.BlockAlign; +} + +static uint32 +wava_Seek (THIS_PTR, uint32 pcm_pos) +{ + TFB_WaveSoundDecoder* wava = (TFB_WaveSoundDecoder*) This; + + if (pcm_pos > wava->max_pcm) + pcm_pos = wava->max_pcm; + wava->cur_pcm = pcm_pos; + uio_fseek (wava->fp, + wava->data_ofs + pcm_pos * wava->FmtHdr.BlockAlign, + SEEK_SET); + + return pcm_pos; +} + +static uint32 +wava_GetFrame (THIS_PTR) +{ + //TFB_WaveSoundDecoder* wava = (TFB_WaveSoundDecoder*) This; + return 0; // only 1 frame for now + + (void)This; // laugh at compiler warning +} diff --git a/sc2/src/sc2code/libs/sound/decoders/wav.h b/sc2/src/sc2code/libs/sound/decoders/wav.h index 725967ced..9aaf3477d 100644 --- a/sc2/src/sc2code/libs/sound/decoders/wav.h +++ b/sc2/src/sc2code/libs/sound/decoders/wav.h @@ -14,16 +14,13 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* Loader for .wav files */ +/* Wave decoder */ #ifndef WAV_H #define WAV_H -#include "port.h" -#include "types.h" -#include "uio.h" +#include "decoder.h" -void LoadWAVFile (uio_DirHandle *dir, const char *file, uint32 *format, - void **data, uint32 *size, uint32 *freq, bool want_big_endian); +extern TFB_SoundDecoderFuncs wava_DecoderVtbl; #endif diff --git a/sc2/src/sc2code/libs/sound/music.c b/sc2/src/sc2code/libs/sound/music.c index 4f0ce1664..d9c05b251 100644 --- a/sc2/src/sc2code/libs/sound/music.c +++ b/sc2/src/sc2code/libs/sound/music.c @@ -164,7 +164,8 @@ _GetMusicData (uio_Stream *fp, DWORD length) } else { - fprintf (stderr, " decoder: %s, rate %d format %x\n", (*pmus)->decoder->decoder_info, + fprintf (stderr, " decoder: %s, rate %d format %x\n", + SoundDecoder_GetName ((*pmus)->decoder), (*pmus)->decoder->frequency, (*pmus)->decoder->format); (*pmus)->num_buffers = 64; diff --git a/sc2/src/sc2code/libs/sound/openal/sound_openal.c b/sc2/src/sc2code/libs/sound/openal/sound_openal.c index 2f6d7d74d..5cf3ccc5c 100644 --- a/sc2/src/sc2code/libs/sound/openal/sound_openal.c +++ b/sc2/src/sc2code/libs/sound/openal/sound_openal.c @@ -21,7 +21,7 @@ ALCcontext *alcContext = NULL; ALCdevice *alcDevice = NULL; -ALfloat listenerPos[] = {0.0f, 0.0f, 0.0f}; +ALfloat listenerPos[] = {0.0f, 0.0f, 0.2f}; ALfloat listenerVel[] = {0.0f, 0.0f, 0.0f}; ALfloat listenerOri[] = {0.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f}; static Task StreamDecoderTask; diff --git a/sc2/src/sc2code/libs/sound/trackplayer.c b/sc2/src/sc2code/libs/sound/trackplayer.c index d5ede8643..a0335e6ee 100644 --- a/sc2/src/sc2code/libs/sound/trackplayer.c +++ b/sc2/src/sc2code/libs/sound/trackplayer.c @@ -436,7 +436,7 @@ SpliceMultiTrack (UNICODE *TrackNames[], UNICODE *TrackText) { fprintf (stderr, " track: %s, decoder: %s, rate %d format %x\n", *TrackNames, - track_decs[tracks]->decoder_info, + SoundDecoder_GetName (track_decs[tracks]), track_decs[tracks]->frequency, track_decs[tracks]->format); SoundDecoder_DecodeAll (track_decs[tracks]); @@ -614,7 +614,7 @@ SpliceTrack (UNICODE *TrackName, UNICODE *TrackText, UNICODE *TimeStamp, TFB_Tra if (last_chain->decoder) { static float old_volume = 0.0f; - if (last_chain->decoder->type == SOUNDDECODER_NULL) + if (last_chain->decoder->is_null) { if (speechVolumeScale != 0.0f) {