Sndlib cleanup: do not expose internals; some dead stuff removed; a few bugs fixed; stream decoder reorg; some memory optimizations; use intptr_t for tags (64-bit cleanliness)

git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@3232 8092fc87-c524-0410-9efc-e669fe64eaf9
This commit is contained in:
avolkov
2009-10-19 19:13:24 +00:00
parent 50f95f5856
commit c6de2bece5
18 changed files with 556 additions and 560 deletions
+2 -9
View File
@@ -69,11 +69,12 @@ extern void PLRPlaySong (MUSIC_REF MusicRef, BOOLEAN Continuous, BYTE
Priority); Priority);
extern void PLRStop (MUSIC_REF MusicRef); extern void PLRStop (MUSIC_REF MusicRef);
extern BOOLEAN PLRPlaying (MUSIC_REF MusicRef); extern BOOLEAN PLRPlaying (MUSIC_REF MusicRef);
extern void PLRSeek (MUSIC_REF MusicRef, DWORD pos);
extern void PLRPause (MUSIC_REF MusicRef); extern void PLRPause (MUSIC_REF MusicRef);
extern void PLRResume (MUSIC_REF MusicRef); extern void PLRResume (MUSIC_REF MusicRef);
extern void snd_PlaySpeech (MUSIC_REF SpeechRef); extern void snd_PlaySpeech (MUSIC_REF SpeechRef);
extern void snd_StopSpeech (void); extern void snd_StopSpeech (void);
extern void PlayChannel (COUNT channel, void *sample, SoundPosition pos, extern void PlayChannel (COUNT channel, SOUND snd, SoundPosition pos,
void *positional_object, unsigned char priority); void *positional_object, unsigned char priority);
extern BOOLEAN ChannelPlaying (COUNT Channel); extern BOOLEAN ChannelPlaying (COUNT Channel);
extern void * GetPositionalObject (COUNT channel); extern void * GetPositionalObject (COUNT channel);
@@ -83,7 +84,6 @@ extern void StopChannel (COUNT Channel, BYTE Priority);
extern void SetMusicVolume (COUNT Volume); extern void SetMusicVolume (COUNT Volume);
extern void SetChannelVolume (COUNT Channel, COUNT Volume, BYTE extern void SetChannelVolume (COUNT Channel, COUNT Volume, BYTE
Priority); Priority);
extern void SetChannelRate (COUNT Channel, DWORD Rate, BYTE Priority);
extern void StopSound (void); extern void StopSound (void);
extern BOOLEAN SoundPlaying (void); extern BOOLEAN SoundPlaying (void);
@@ -91,13 +91,6 @@ extern BOOLEAN SoundPlaying (void);
extern void WaitForSoundEnd (COUNT Channel); extern void WaitForSoundEnd (COUNT Channel);
#define TFBSOUND_WAIT_ALL ((COUNT)~0) #define TFBSOUND_WAIT_ALL ((COUNT)~0)
extern BOOLEAN AllocHardwareSample (BYTE *lpSnd, DWORD SampleRate, COUNT
SampleLength, COUNT LoopBegin, COUNT LoopLen);
extern BOOLEAN FreeHardwareSample (BYTE *lpSnd, COUNT SampleLength);
extern COUNT GetSampleRate (SOUND Sound);
extern COUNT GetSampleLength (SOUND Sound);
extern BYTE* GetSampleAddress (SOUND Sound);
extern DWORD FadeMusic (BYTE end_vol, SIZE TimeInterval); extern DWORD FadeMusic (BYTE end_vol, SIZE TimeInterval);
#endif /* _SNDLIB_H */ #endif /* _SNDLIB_H */
+2
View File
@@ -575,6 +575,8 @@ SoundDecoder_DecodeAll (TFB_SoundDecoder *decoder)
} }
decoder->buffer_size = decoded_bytes; decoder->buffer_size = decoded_bytes;
decoder->pos += decoded_bytes; decoder->pos += decoded_bytes;
// Free up some unused memory
decoder->buffer = HRealloc (decoder->buffer, decoded_bytes);
if (decoder->need_swap && decoded_bytes > 0 && if (decoder->need_swap && decoded_bytes > 0 &&
(decoder->format == decoder_formats.stereo16 || (decoder->format == decoder_formats.stereo16 ||
+1
View File
@@ -16,6 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
#include "sound.h"
#include "sndintrn.h" #include "sndintrn.h"
#include "options.h" #include "options.h"
#include "libs/reslib.h" #include "libs/reslib.h"
@@ -1,5 +1,3 @@
//Copyright Paul Reiche, Fred Ford. 1992-2002
/* /*
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -20,6 +18,7 @@
*/ */
#include "audiodrv_nosound.h" #include "audiodrv_nosound.h"
#include "../../sndintrn.h"
#include "libs/tasklib.h" #include "libs/tasklib.h"
#include "libs/log.h" #include "libs/log.h"
#include "libs/memlib.h" #include "libs/memlib.h"
@@ -136,13 +135,7 @@ noSound_Init (audio_Driver *driver, sint32 flags)
for (i = 0; i < NUM_SOUNDSOURCES; ++i) for (i = 0; i < NUM_SOUNDSOURCES; ++i)
{ {
audio_GenSources (1, &soundSource[i].handle); audio_GenSources (1, &soundSource[i].handle);
soundSource[i].sample = NULL;
soundSource[i].stream_should_be_playing = FALSE;
soundSource[i].stream_mutex = CreateMutex ("Nosound stream mutex", SYNC_CLASS_AUDIO); soundSource[i].stream_mutex = CreateMutex ("Nosound stream mutex", SYNC_CLASS_AUDIO);
soundSource[i].sbuffer = NULL;
soundSource[i].sbuf_start = 0;
soundSource[i].sbuf_size = 0;
soundSource[i].sbuf_offset = 0;
} }
atexit (unInitAudio); atexit (unInitAudio);
@@ -24,6 +24,7 @@
#include "libs/sound/sound.h" #include "libs/sound/sound.h"
#include "libs/sound/mixer/mixer.h" #include "libs/sound/mixer/mixer.h"
/* Playback task */ /* Playback task */
int PlaybackTaskFunc (void *data); int PlaybackTaskFunc (void *data);
+1 -8
View File
@@ -1,5 +1,3 @@
//Copyright Paul Reiche, Fred Ford. 1992-2002
/* /*
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -20,6 +18,7 @@
*/ */
#include "audiodrv_sdl.h" #include "audiodrv_sdl.h"
#include "../../sndintrn.h"
#include "libs/tasklib.h" #include "libs/tasklib.h"
#include "libs/log.h" #include "libs/log.h"
#include "libs/memlib.h" #include "libs/memlib.h"
@@ -200,13 +199,7 @@ mixSDL_Init (audio_Driver *driver, sint32 flags)
for (i = 0; i < NUM_SOUNDSOURCES; ++i) for (i = 0; i < NUM_SOUNDSOURCES; ++i)
{ {
audio_GenSources (1, &soundSource[i].handle); audio_GenSources (1, &soundSource[i].handle);
soundSource[i].sample = NULL;
soundSource[i].stream_should_be_playing = FALSE;
soundSource[i].stream_mutex = CreateMutex ("MixSDL stream mutex", SYNC_CLASS_AUDIO); soundSource[i].stream_mutex = CreateMutex ("MixSDL stream mutex", SYNC_CLASS_AUDIO);
soundSource[i].sbuffer = NULL;
soundSource[i].sbuf_start = 0;
soundSource[i].sbuf_size = 0;
soundSource[i].sbuf_offset = 0;
} }
atexit (unInitAudio); atexit (unInitAudio);
+50 -46
View File
@@ -18,6 +18,7 @@
#include "libs/file.h" #include "libs/file.h"
#include "options.h" #include "options.h"
#include "sound.h" #include "sound.h"
#include "sndintrn.h"
#include "libs/reslib.h" #include "libs/reslib.h"
#include "libs/log.h" #include "libs/log.h"
#include "libs/memlib.h" #include "libs/memlib.h"
@@ -74,6 +75,17 @@ PLRPlaying (MUSIC_REF MusicRef)
return FALSE; return FALSE;
} }
void
PLRSeek (MUSIC_REF MusicRef, DWORD pos)
{
if (MusicRef == curMusicRef || MusicRef == (MUSIC_REF)~0)
{
LockMutex (soundSource[MUSIC_SOURCE].stream_mutex);
SeekStream (MUSIC_SOURCE, pos);
UnlockMutex (soundSource[MUSIC_SOURCE].stream_mutex);
}
}
void void
PLRPause (MUSIC_REF MusicRef) PLRPause (MUSIC_REF MusicRef)
{ {
@@ -152,46 +164,39 @@ void *
_GetMusicData (uio_Stream *fp, DWORD length) _GetMusicData (uio_Stream *fp, DWORD length)
{ {
MUSIC_REF h; MUSIC_REF h;
TFB_SoundSample *sample;
TFB_SoundDecoder *decoder;
char filename[256];
if (_cur_resfile_name && (h = AllocMusicData (sizeof (void *)))) if (!_cur_resfile_name)
return NULL;
strncpy (filename, _cur_resfile_name, sizeof(filename) - 1);
filename[sizeof(filename) - 1] = '\0';
CheckMusicResName (filename);
log_add (log_Info, "_GetMusicData(): loading %s", filename);
decoder = SoundDecoder_Load (contentDir, filename, 4096, 0, 0);
if (!decoder)
{ {
TFB_SoundSample **pmus = h; log_add (log_Warning, "_GetMusicData(): couldn't load %s", filename);
return NULL;
if (!pmus)
{
return NULL;
}
else
{
char filename[256];
*pmus = (TFB_SoundSample *) HCalloc (sizeof (TFB_SoundSample));
strncpy (filename, _cur_resfile_name, sizeof(filename) - 1);
filename[sizeof(filename) - 1] = '\0';
CheckMusicResName (filename);
log_add (log_Info, "_GetMusicData(): loading %s", filename);
if (((*pmus)->decoder = SoundDecoder_Load (contentDir, filename,
4096, 0, 0)) == 0)
{
log_add (log_Warning, "_GetMusicData(): couldn't load %s", filename);
HFree (h);
return NULL;
}
else
{
log_add (log_Info, " decoder: %s, rate %d format %x",
SoundDecoder_GetName ((*pmus)->decoder),
(*pmus)->decoder->frequency, (*pmus)->decoder->format);
(*pmus)->num_buffers = 64;
(*pmus)->buffer = (audio_Object *) HMalloc (sizeof (audio_Object) * (*pmus)->num_buffers);
audio_GenBuffers ((*pmus)->num_buffers, (*pmus)->buffer);
}
}
} }
h = AllocMusicData (sizeof (void *));
if (!h)
{
SoundDecoder_Free (decoder);
return NULL;
}
sample = TFB_CreateSoundSample (decoder, 64, NULL);
*h = sample;
log_add (log_Info, " decoder: %s, rate %d format %x",
SoundDecoder_GetName (sample->decoder),
sample->decoder->frequency, sample->decoder->format);
(void) fp; /* satisfy compiler (unused parameter) */ (void) fp; /* satisfy compiler (unused parameter) */
(void) length; /* satisfy compiler (unused parameter) */ (void) length; /* satisfy compiler (unused parameter) */
return (h); return (h);
@@ -201,28 +206,27 @@ BOOLEAN
_ReleaseMusicData (void *data) _ReleaseMusicData (void *data)
{ {
TFB_SoundSample **pmus = data; TFB_SoundSample **pmus = data;
TFB_SoundSample *sample;
if (pmus == NULL) if (pmus == NULL)
return (FALSE); return (FALSE);
if ((*pmus)->decoder) sample = *pmus;
assert (sample != 0);
if (sample->decoder)
{ {
TFB_SoundDecoder *decoder = (*pmus)->decoder; TFB_SoundDecoder *decoder = sample->decoder;
LockMutex (soundSource[MUSIC_SOURCE].stream_mutex); LockMutex (soundSource[MUSIC_SOURCE].stream_mutex);
if (soundSource[MUSIC_SOURCE].sample == (*pmus)) if (soundSource[MUSIC_SOURCE].sample == sample)
{ { // Currently playing this sample! Not good.
StopStream (MUSIC_SOURCE); StopStream (MUSIC_SOURCE);
} }
UnlockMutex (soundSource[MUSIC_SOURCE].stream_mutex); UnlockMutex (soundSource[MUSIC_SOURCE].stream_mutex);
(*pmus)->decoder = NULL; sample->decoder = NULL;
SoundDecoder_Free (decoder); SoundDecoder_Free (decoder);
audio_DeleteBuffers ((*pmus)->num_buffers, (*pmus)->buffer);
HFree ((*pmus)->buffer);
if ((*pmus)->buffer_tag)
HFree ((*pmus)->buffer_tag);
} }
HFree (*pmus); TFB_DestroySoundSample (sample);
HFree (pmus); HFree (pmus);
return (TRUE); return (TRUE);
+1 -6
View File
@@ -21,6 +21,7 @@
#include "audiodrv_openal.h" #include "audiodrv_openal.h"
#include "../sndintrn.h"
#include "libs/tasklib.h" #include "libs/tasklib.h"
#include "libs/log.h" #include "libs/log.h"
#include "libs/memlib.h" #include "libs/memlib.h"
@@ -182,13 +183,7 @@ openAL_Init (audio_Driver *driver, sint32 flags)
alSourcefv (soundSource[i].handle, AL_VELOCITY, zero); alSourcefv (soundSource[i].handle, AL_VELOCITY, zero);
alSourcefv (soundSource[i].handle, AL_DIRECTION, zero); alSourcefv (soundSource[i].handle, AL_DIRECTION, zero);
soundSource[i].sample = NULL;
soundSource[i].stream_should_be_playing = FALSE;
soundSource[i].stream_mutex = CreateMutex ("OpenAL stream mutex", SYNC_CLASS_AUDIO); soundSource[i].stream_mutex = CreateMutex ("OpenAL stream mutex", SYNC_CLASS_AUDIO);
soundSource[i].sbuffer = NULL;
soundSource[i].sbuf_start = 0;
soundSource[i].sbuf_size = 0;
soundSource[i].sbuf_offset = 0;
} }
SetSFXVolume (sfxVolumeScale); SetSFXVolume (sfxVolumeScale);
+1
View File
@@ -16,6 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
#include "sound.h"
#include "sndintrn.h" #include "sndintrn.h"
static void static void
+88 -137
View File
@@ -16,6 +16,7 @@
#include "options.h" #include "options.h"
#include "sound.h" #include "sound.h"
#include "sndintrn.h"
#include "libs/reslib.h" #include "libs/reslib.h"
#include "libs/log.h" #include "libs/log.h"
#include "libs/strings/strintrn.h" #include "libs/strings/strintrn.h"
@@ -27,24 +28,30 @@ static void CheckFinishedChannels (void);
void void
PlayChannel (COUNT channel, void *sample, SoundPosition pos, PlayChannel (COUNT channel, SOUND snd, SoundPosition pos,
void *positional_object, unsigned char priority) void *positional_object, unsigned char priority)
{ {
TFB_SoundSample *tfb_sample = *(TFB_SoundSample**) sample; void *snd_ptr = GetSoundAddress (snd);
TFB_SoundSample *sample;
StopSource (channel); StopSource (channel);
// all finished (stopped) channels can be cleaned up at this point // all finished (stopped) channels can be cleaned up at this point
// since this is the only func that can initiate an sfx sound // since this is the only func that can initiate an sfx sound
CheckFinishedChannels (); CheckFinishedChannels ();
soundSource[channel].sample = tfb_sample; if (!snd_ptr)
return; // nothing to play
sample = *(TFB_SoundSample**) snd_ptr;
soundSource[channel].sample = sample;
soundSource[channel].positional_object = positional_object; soundSource[channel].positional_object = positional_object;
if (optStereoSFX) if (optStereoSFX)
UpdateSoundPosition (channel, pos); UpdateSoundPosition (channel, pos);
audio_Sourcei (soundSource[channel].handle, audio_BUFFER, audio_Sourcei (soundSource[channel].handle, audio_BUFFER,
tfb_sample->buffer[0]); sample->buffer[0]);
audio_SourcePlay (soundSource[channel].handle); audio_SourcePlay (soundSource[channel].handle);
(void) priority; (void) priority;
} }
@@ -145,39 +152,6 @@ SetChannelVolume (COUNT channel, COUNT volume, BYTE priority)
(void)priority; // ignored (void)priority; // ignored
} }
// Status: Ignored
BYTE*
GetSampleAddress (SOUND sound)
// I might be prototyping this wrong, type-wise.
{
return ((BYTE*)GetSoundAddress (sound));
}
// Status: Ignored
COUNT
GetSampleLength (SOUND sound)
{
(void)sound;
return 0;
}
// Status: Ignored
void
SetChannelRate (COUNT channel, DWORD rate_hz, unsigned char priority)
{
(void) channel;
(void) rate_hz;
(void) priority;
}
// Status: Ignored
COUNT
GetSampleRate (SOUND sound)
{
(void) sound;
return 0;
}
void * void *
_GetSoundBankData (uio_Stream *fp, DWORD length) _GetSoundBankData (uio_Stream *fp, DWORD length)
{ {
@@ -187,6 +161,8 @@ _GetSoundBankData (uio_Stream *fp, DWORD length)
#define MAX_FX 256 #define MAX_FX 256
TFB_SoundSample *sndfx[MAX_FX]; TFB_SoundSample *sndfx[MAX_FX];
STRING_TABLE Snd; STRING_TABLE Snd;
STRING str;
int i;
(void) length; // ignored (void) length; // ignored
opos = uio_ftell (fp); opos = uio_ftell (fp);
@@ -211,82 +187,65 @@ _GetSoundBankData (uio_Stream *fp, DWORD length)
while (uio_fgets (CurrentLine, sizeof (CurrentLine), fp) && while (uio_fgets (CurrentLine, sizeof (CurrentLine), fp) &&
snd_ct < MAX_FX) snd_ct < MAX_FX)
{ {
if (sscanf(CurrentLine, "%s", &filename[n]) == 1) TFB_SoundSample* sample;
TFB_SoundDecoder* decoder;
uint32 decoded_bytes;
if (sscanf (CurrentLine, "%s", &filename[n]) != 1)
{ {
log_add (log_Info, "_GetSoundBankData(): loading %s", filename); log_add (log_Warning, "_GetSoundBankData: bad line: '%s'",
CurrentLine);
sndfx[snd_ct] = (TFB_SoundSample *) HCalloc (sizeof (TFB_SoundSample)); continue;
sndfx[snd_ct]->decoder = SoundDecoder_Load (contentDir,
filename, 4096, 0, 0);
if (!sndfx[snd_ct]->decoder)
{
log_add (log_Warning, "_GetSoundBankData(): couldn't load %s", filename);
HFree (sndfx[snd_ct]);
}
else
{
uint32 decoded_bytes;
decoded_bytes = SoundDecoder_DecodeAll (sndfx[snd_ct]->decoder);
log_add (log_Info, "_GetSoundBankData(): decoded_bytes %d", decoded_bytes);
sndfx[snd_ct]->num_buffers = 1;
sndfx[snd_ct]->buffer = (audio_Object *) HMalloc (
sizeof (audio_Object) * sndfx[snd_ct]->num_buffers);
audio_GenBuffers (sndfx[snd_ct]->num_buffers, sndfx[snd_ct]->buffer);
audio_BufferData (sndfx[snd_ct]->buffer[0], sndfx[snd_ct]->decoder->format,
sndfx[snd_ct]->decoder->buffer, decoded_bytes,
sndfx[snd_ct]->decoder->frequency);
SoundDecoder_Free (sndfx[snd_ct]->decoder);
sndfx[snd_ct]->decoder = NULL;
++snd_ct;
}
}
else
{
log_add (log_Warning, "_GetSoundBankData: Bad file!");
} }
// pkunk insult fix 2002/11/12 (ftell shouldn't be needed for loop to terminate) log_add (log_Info, "_GetSoundBankData(): loading %s", filename);
/*if (uio_ftell (fp) - opos >= length)
break;*/ decoder = SoundDecoder_Load (contentDir, filename, 4096, 0, 0);
if (!decoder)
{
log_add (log_Warning, "_GetSoundBankData(): couldn't load %s",
filename);
continue;
}
// SFX samples don't have decoders, everything is pre-decoded below
sample = TFB_CreateSoundSample (NULL, 1, NULL);
// Decode everything and stash it in 1 buffer
decoded_bytes = SoundDecoder_DecodeAll (decoder);
log_add (log_Info, "_GetSoundBankData(): decoded bytes %d",
decoded_bytes);
audio_BufferData (sample->buffer[0], decoder->format,
decoder->buffer, decoded_bytes, decoder->frequency);
// just for informational purposes
sample->length = decoder->length;
SoundDecoder_Free (decoder);
sndfx[snd_ct] = sample;
++snd_ct;
} }
Snd = NULL; if (!snd_ct)
if (snd_ct && (Snd = AllocStringTable (snd_ct, 0))) return NULL; // no sounds decoded
Snd = AllocStringTable (snd_ct, 0);
if (!Snd)
{ // Oops, have to delete everything now
while (snd_ct--)
TFB_DestroySoundSample (sndfx[snd_ct]);
return NULL;
}
// Populate the STRING_TABLE with ptrs to sample
for (i = 0, str = Snd->strings; i < snd_ct; ++i, ++str)
{ {
STRING_TABLE fxTab = Snd; TFB_SoundSample **target = HMalloc (sizeof (sndfx[0]));
*target = sndfx[i];
if (fxTab == 0) str->data = (STRINGPTR)target;
{ str->length = sizeof (sndfx[0]);
while (snd_ct--)
{
if (sndfx[snd_ct]->decoder)
SoundDecoder_Free (sndfx[snd_ct]->decoder);
HFree (sndfx[snd_ct]);
}
FreeStringTable (Snd);
Snd = 0;
}
else
{
STRING str;
int i;
str = fxTab->strings;
for (i = 0; i < snd_ct; i++)
{
TFB_SoundSample **target = HMalloc (sizeof (sndfx[0]));
*target = sndfx[i];
str->data = (STRINGPTR)target;
str->length = sizeof (sndfx[0]);
str++;
}
}
} }
return Snd; return Snd;
@@ -296,45 +255,37 @@ BOOLEAN
_ReleaseSoundBankData (void *Snd) _ReleaseSoundBankData (void *Snd)
{ {
STRING_TABLE fxTab = Snd; STRING_TABLE fxTab = Snd;
int index;
if (!fxTab)
return FALSE;
if (fxTab) for (index = 0; index < fxTab->size; ++index)
{ {
int snd_ct, index; int i;
TFB_SoundSample **sptr; void **sptr = (void**)fxTab->strings[index].data;
TFB_SoundSample *sample = (TFB_SoundSample*)*sptr;
snd_ct = fxTab->size; // Check all sources and see if we are currently playing this sample
index = 0; for (i = 0; i < NUM_SOUNDSOURCES; ++i)
while (snd_ct--)
{ {
int i; if (soundSource[i].sample == sample)
{ // Playing this sample. Have to stop it.
sptr = (TFB_SoundSample **)(fxTab->strings[index].data); StopSource (i);
soundSource[i].sample = NULL;
for (i = 0; i < NUM_SOUNDSOURCES; ++i)
{
if (soundSource[i].sample == (*sptr))
{
StopSource (i);
soundSource[i].sample = NULL;
}
} }
if ((*sptr)->decoder)
SoundDecoder_Free ((*sptr)->decoder);
audio_DeleteBuffers ((*sptr)->num_buffers, (*sptr)->buffer);
HFree ((*sptr)->buffer);
if ((*sptr)->buffer_tag)
HFree ((*sptr)->buffer_tag);
HFree (*sptr);
*sptr = 0;
index++;
} }
FreeStringTable (Snd);
return (TRUE); if (sample->decoder)
SoundDecoder_Free (sample->decoder);
sample->decoder = NULL;
TFB_DestroySoundSample (sample);
// sptr will be deleted by FreeStringTable() below
} }
FreeStringTable (fxTab);
return (FALSE); return TRUE;
} }
BOOLEAN BOOLEAN
+39 -2
View File
@@ -20,10 +20,12 @@
#define _SNDINTRN_H #define _SNDINTRN_H
#include <stdio.h> #include <stdio.h>
#include "libs/sndlib.h" #include "types.h"
#include "libs/reslib.h" #include "libs/reslib.h"
#include "libs/memlib.h" #include "libs/memlib.h"
#define PAD_SCOPE_BYTES 256
extern void *_GetMusicData (uio_Stream *fp, DWORD length); extern void *_GetMusicData (uio_Stream *fp, DWORD length);
extern BOOLEAN _ReleaseMusicData (void *handle); extern BOOLEAN _ReleaseMusicData (void *handle);
@@ -35,5 +37,40 @@ extern BOOLEAN _ReleaseSoundBankData (void *handle);
extern char* CheckMusicResName (char* filename); extern char* CheckMusicResName (char* filename);
#endif /* _SNDINTRN_H */ // audio data
struct tfb_soundsample
{
TFB_SoundDecoder *decoder; // decoder to read from
float length; // total length of decoder chain in seconds
audio_Object *buffer;
uint32 num_buffers;
TFB_SoundTag *buffer_tag;
sint32 offset; // initial offset
intptr_t data; // user-defined data
TFB_SoundCallbacks callbacks; // user-defined callbacks
};
// equivalent to channel in legacy sound code
typedef struct tfb_soundsource
{
TFB_SoundSample *sample;
audio_Object handle;
bool stream_should_be_playing;
Mutex stream_mutex;
sint32 start_time; // for tracks played-time math
uint32 pause_time; // keep track for paused tracks
void *positional_object;
audio_Object last_q_buf; // for callbacks processing
// Cyclic waveform buffer for oscilloscope
void *sbuffer;
uint32 sbuf_size;
uint32 sbuf_tail;
uint32 sbuf_head;
uint32 sbuf_lasttime; // timestamp of the first queued buffer
} TFB_SoundSource;
extern TFB_SoundSource soundSource[];
#endif /* _SNDINTRN_H */
+1
View File
@@ -17,6 +17,7 @@
*/ */
#include "sound.h" #include "sound.h"
#include "sndintrn.h"
#include "libs/compiler.h" #include "libs/compiler.h"
#include "libs/tasklib.h" #include "libs/tasklib.h"
#include "libs/inplib.h" #include "libs/inplib.h"
+16 -38
View File
@@ -17,10 +17,11 @@
#ifndef _UQM_SOUND_H // try avoiding collisions on id #ifndef _UQM_SOUND_H // try avoiding collisions on id
#define _UQM_SOUND_H #define _UQM_SOUND_H
#include "sndintrn.h" #include "types.h"
#include "audiocore.h" #include "audiocore.h"
#include "decoders/decoder.h" #include "decoders/decoder.h"
#include "libs/threadlib.h" #include "libs/threadlib.h"
#include "libs/sndlib.h"
#define FIRST_SFX_SOURCE 0 #define FIRST_SFX_SOURCE 0
@@ -28,13 +29,12 @@
#define MUSIC_SOURCE (LAST_SFX_SOURCE + 1) #define MUSIC_SOURCE (LAST_SFX_SOURCE + 1)
#define SPEECH_SOURCE (MUSIC_SOURCE + 1) #define SPEECH_SOURCE (MUSIC_SOURCE + 1)
#define NUM_SOUNDSOURCES (SPEECH_SOURCE + 1) #define NUM_SOUNDSOURCES (SPEECH_SOURCE + 1)
#define PAD_SCOPE_BYTES 8096
typedef struct typedef struct
{ {
int in_use; int in_use;
audio_Object buf_name; audio_Object buf_name;
void *data; // user-defined data intptr_t data; // user-defined data
} TFB_SoundTag; } TFB_SoundTag;
typedef struct tfb_soundcallbacks typedef struct tfb_soundcallbacks
@@ -51,41 +51,6 @@ typedef struct tfb_soundcallbacks
void (* OnQueueBuffer) (TFB_SoundSample*, audio_Object); void (* OnQueueBuffer) (TFB_SoundSample*, audio_Object);
} TFB_SoundCallbacks; } TFB_SoundCallbacks;
// audio data
struct tfb_soundsample
{
TFB_SoundDecoder *decoder; // decoder to read from
float length; // total length of decoder chain in seconds
audio_Object *buffer;
uint32 num_buffers;
TFB_SoundTag *buffer_tag;
sint32 offset; // initial offset
void* data; // user-defined data
TFB_SoundCallbacks callbacks; // user-defined callbacks
};
// equivalent to channel in legacy sound code
typedef struct tfb_soundsource
{
TFB_SoundSample *sample;
audio_Object handle;
bool stream_should_be_playing;
Mutex stream_mutex;
sint32 start_time;
void *positional_object;
// Cyclic waveform buffer for oscilloscope
void *sbuffer;
uint32 sbuf_start; // cyclic buffer tail (confusing, eh?)
uint32 sbuf_size;
uint32 sbuf_offset; // cyclic buffer head
uint32 sbuf_lasttime;
// keep track for paused tracks
uint32 pause_time;
} TFB_SoundSource;
extern TFB_SoundSource soundSource[];
extern int musicVolume; extern int musicVolume;
extern float musicVolumeScale; extern float musicVolumeScale;
@@ -98,6 +63,19 @@ void CleanSource (int iSource);
void SetSFXVolume (float volume); void SetSFXVolume (float volume);
void SetSpeechVolume (float volume); void SetSpeechVolume (float volume);
TFB_SoundSample *TFB_CreateSoundSample (TFB_SoundDecoder*, uint32 num_buffers,
const TFB_SoundCallbacks* /* can be NULL */);
void TFB_DestroySoundSample (TFB_SoundSample*);
void TFB_SetSoundSampleData (TFB_SoundSample*, intptr_t data);
intptr_t TFB_GetSoundSampleData (TFB_SoundSample*);
void TFB_SetSoundSampleCallbacks (TFB_SoundSample*,
const TFB_SoundCallbacks* /* can be NULL */);
TFB_SoundDecoder* TFB_GetSoundSampleDecoder (TFB_SoundSample*);
TFB_SoundTag* TFB_FindTaggedBuffer (TFB_SoundSample*, audio_Object buffer);
void TFB_ClearBufferTag (TFB_SoundTag*);
bool TFB_TagBuffer (TFB_SoundSample*, audio_Object buffer, intptr_t data);
#include "stream.h" #include "stream.h"
#endif // _UQM_SOUND_H #endif // _UQM_SOUND_H
+317 -256
View File
@@ -19,17 +19,22 @@
#include <stdlib.h> #include <stdlib.h>
// for abs() // for abs()
#include "sound.h" #include "sound.h"
#include "sndintrn.h"
#include "libs/tasklib.h" #include "libs/tasklib.h"
#include "libs/log.h" #include "libs/log.h"
#include "libs/memlib.h" #include "libs/memlib.h"
static void add_scope_data (TFB_SoundSource *source, uint32 bytes);
void void
PlayStream (TFB_SoundSample *sample, uint32 source, bool looping, bool scope, PlayStream (TFB_SoundSample *sample, uint32 source, bool looping, bool scope,
bool rewind) bool rewind)
{ {
uint32 i, pos = 0; uint32 i;
sint32 offset = 0; sint32 offset;
TFB_SoundDecoder *decoder;
if (!sample) if (!sample)
return; return;
@@ -43,64 +48,65 @@ PlayStream (TFB_SoundSample *sample, uint32 source, bool looping, bool scope,
memset (sample->buffer_tag, 0, memset (sample->buffer_tag, 0,
sample->num_buffers * sizeof (sample->buffer_tag[0])); sample->num_buffers * sizeof (sample->buffer_tag[0]));
decoder = sample->decoder;
offset = sample->offset; offset = sample->offset;
if (rewind) if (rewind)
SoundDecoder_Rewind (sample->decoder); SoundDecoder_Rewind (decoder);
else else
offset += (sint32)(SoundDecoder_GetTime (sample->decoder) * offset += (sint32)(SoundDecoder_GetTime (decoder) * ONE_SECOND);
(float)ONE_SECOND);
soundSource[source].sample = sample; soundSource[source].sample = sample;
soundSource[source].sample->decoder->looping = looping; decoder->looping = looping;
audio_Sourcei (soundSource[source].handle, audio_LOOPING, false); audio_Sourcei (soundSource[source].handle, audio_LOOPING, false);
if (scope) if (scope)
{ { // Prealloc the scope buffer in advance so that we do not
soundSource[source].sbuffer = HMalloc (PAD_SCOPE_BYTES); // realloc it a zillion times
soundSource[source].sbuf_size = sample->num_buffers *
decoder->buffer_size + PAD_SCOPE_BYTES;
soundSource[source].sbuffer = HMalloc (soundSource[source].sbuf_size);
} }
for (i = 0; i < sample->num_buffers; ++i) for (i = 0; i < sample->num_buffers; ++i)
{ {
uint32 decoded_bytes; uint32 decoded_bytes;
decoded_bytes = SoundDecoder_Decode (sample->decoder); decoded_bytes = SoundDecoder_Decode (decoder);
#if 0 #if 0
log_add (log_Debug, "PlayStream(): source:%d filename:%s start:%d position:%d bytes:%d\n", log_add (log_Debug, "PlayStream(): source:%d filename:%s start:%d "
source, sample->decoder->filename, sample->decoder->start_sample, "position:%d bytes:%d\n",
sample->decoder->pos, decoded_bytes); source, decoder->filename, decoder->start_sample,
decoder->pos, decoded_bytes);
#endif #endif
if (decoded_bytes == 0) if (decoded_bytes == 0)
break; break;
audio_BufferData (sample->buffer[i], sample->decoder->format, audio_BufferData (sample->buffer[i], decoder->format,
sample->decoder->buffer, decoded_bytes, decoder->buffer, decoded_bytes, decoder->frequency);
sample->decoder->frequency);
audio_SourceQueueBuffers (soundSource[source].handle, 1, audio_SourceQueueBuffers (soundSource[source].handle, 1,
&sample->buffer[i]); &sample->buffer[i]);
if (sample->callbacks.OnQueueBuffer) if (sample->callbacks.OnQueueBuffer)
sample->callbacks.OnQueueBuffer (sample, sample->buffer[i]); sample->callbacks.OnQueueBuffer (sample, sample->buffer[i]);
if (scope) if (scope)
{ add_scope_data (&soundSource[source], decoded_bytes);
UBYTE *p;
soundSource[source].sbuffer = HRealloc (
soundSource[source].sbuffer,
pos + decoded_bytes + PAD_SCOPE_BYTES);
p = (UBYTE *)soundSource[source].sbuffer;
memcpy (&p[pos], sample->decoder->buffer, decoded_bytes);
pos += decoded_bytes;
}
if (sample->decoder->error) if (decoder->error != SOUNDDECODER_OK)
{ {
if (sample->decoder->error != SOUNDDECODER_EOF || if (decoder->error != SOUNDDECODER_EOF ||
!sample->callbacks.OnEndChunk || !sample->callbacks.OnEndChunk ||
!sample->callbacks.OnEndChunk (sample, sample->buffer[i])) !sample->callbacks.OnEndChunk (sample, sample->buffer[i]))
{ // Decoder probably run out of data before we could fill
// all buffers, and OnEndChunk() did not set a new one
break; break;
}
else
{ // OnEndChunk() probably set a new decoder, get it
decoder = sample->decoder;
}
} }
} }
soundSource[source].sbuf_size = pos + PAD_SCOPE_BYTES;
soundSource[source].sbuf_start = pos;
soundSource[source].sbuf_lasttime = GetTimeCounter (); soundSource[source].sbuf_lasttime = GetTimeCounter ();
// Adjust the start time so it looks like the stream has been playing // Adjust the start time so it looks like the stream has been playing
// from the very beginning // from the very beginning
@@ -124,9 +130,9 @@ StopStream (uint32 source)
soundSource[source].sbuffer = NULL; soundSource[source].sbuffer = NULL;
HFree (sbuffer); HFree (sbuffer);
} }
soundSource[source].sbuf_start = 0;
soundSource[source].sbuf_size = 0; soundSource[source].sbuf_size = 0;
soundSource[source].sbuf_offset = 0; soundSource[source].sbuf_head = 0;
soundSource[source].sbuf_tail = 0;
soundSource[source].pause_time = 0; soundSource[source].pause_time = 0;
} }
@@ -176,11 +182,73 @@ PlayingStream (uint32 source)
return soundSource[source].stream_should_be_playing; return soundSource[source].stream_should_be_playing;
} }
TFB_SoundSample *
TFB_CreateSoundSample (TFB_SoundDecoder *decoder, uint32 num_buffers,
const TFB_SoundCallbacks *pcbs /* can be NULL */)
{
TFB_SoundSample *sample;
sample = HCalloc (sizeof (*sample));
sample->decoder = decoder;
sample->num_buffers = num_buffers;
sample->buffer = HCalloc (sizeof (audio_Object) * num_buffers);
audio_GenBuffers (num_buffers, sample->buffer);
if (pcbs)
sample->callbacks = *pcbs;
return sample;
}
// Deletes all TFB_SoundSample data structures, except decoder
void
TFB_DestroySoundSample (TFB_SoundSample *sample)
{
if (sample->buffer)
{
audio_DeleteBuffers (sample->num_buffers, sample->buffer);
HFree (sample->buffer);
}
HFree (sample->buffer_tag);
HFree (sample);
}
void
TFB_SetSoundSampleData (TFB_SoundSample *sample, intptr_t data)
{
sample->data = data;
}
intptr_t
TFB_GetSoundSampleData (TFB_SoundSample *sample)
{
return sample->data;
}
void
TFB_SetSoundSampleCallbacks (TFB_SoundSample *sample,
const TFB_SoundCallbacks *pcbs /* can be NULL */)
{
if (pcbs)
sample->callbacks = *pcbs;
else
memset (&sample->callbacks, 0, sizeof (sample->callbacks));
}
TFB_SoundDecoder*
TFB_GetSoundSampleDecoder (TFB_SoundSample *sample)
{
return sample->decoder;
}
TFB_SoundTag* TFB_SoundTag*
TFB_FindTaggedBuffer (TFB_SoundSample* sample, audio_Object buffer) TFB_FindTaggedBuffer (TFB_SoundSample *sample, audio_Object buffer)
{ {
uint32 buf_num; uint32 buf_num;
if (!sample->buffer_tag)
return NULL; // do not have any tags
for (buf_num = 0; for (buf_num = 0;
buf_num < sample->num_buffers && buf_num < sample->num_buffers &&
(!sample->buffer_tag[buf_num].in_use || (!sample->buffer_tag[buf_num].in_use ||
@@ -193,11 +261,15 @@ TFB_FindTaggedBuffer (TFB_SoundSample* sample, audio_Object buffer)
&sample->buffer_tag[buf_num] : NULL; &sample->buffer_tag[buf_num] : NULL;
} }
void bool
TFB_TagBuffer (TFB_SoundSample* sample, audio_Object buffer, void* data) TFB_TagBuffer (TFB_SoundSample *sample, audio_Object buffer, intptr_t data)
{ {
uint32 buf_num; uint32 buf_num;
if (!sample->buffer_tag)
sample->buffer_tag = HCalloc (sizeof (TFB_SoundTag) *
sample->num_buffers);
for (buf_num = 0; for (buf_num = 0;
buf_num < sample->num_buffers && buf_num < sample->num_buffers &&
sample->buffer_tag[buf_num].in_use && sample->buffer_tag[buf_num].in_use &&
@@ -206,258 +278,247 @@ TFB_TagBuffer (TFB_SoundSample* sample, audio_Object buffer, void* data)
; ;
if (buf_num >= sample->num_buffers) if (buf_num >= sample->num_buffers)
return; // no empty slot return false; // no empty slot
sample->buffer_tag[buf_num].in_use = 1; sample->buffer_tag[buf_num].in_use = 1;
sample->buffer_tag[buf_num].buf_name = buffer; sample->buffer_tag[buf_num].buf_name = buffer;
sample->buffer_tag[buf_num].data = data; sample->buffer_tag[buf_num].data = data;
return true;
} }
void void
TFB_ClearBufferTag (TFB_SoundTag* ptag) TFB_ClearBufferTag (TFB_SoundTag *ptag)
{ {
ptag->in_use = 0; ptag->in_use = 0;
ptag->buf_name = 0; ptag->buf_name = 0;
} }
static void
remove_scope_data (TFB_SoundSource *source, audio_Object buffer)
{
audio_IntVal buf_size;
audio_GetBufferi (buffer, audio_SIZE, &buf_size);
source->sbuf_head += buf_size;
// the buffer is cyclic
source->sbuf_head %= source->sbuf_size;
source->sbuf_lasttime = GetTimeCounter ();
}
static void
add_scope_data (TFB_SoundSource *source, uint32 bytes)
{
uint8 *sbuffer = source->sbuffer;
uint8 *dec_buf = source->sample->decoder->buffer;
uint32 tail_bytes;
uint32 wrap_bytes;
if (source->sbuf_tail + bytes > source->sbuf_size)
{ // does not fit at the tail, have to split it up
tail_bytes = source->sbuf_size - source->sbuf_tail;
wrap_bytes = bytes - tail_bytes;
}
else
{ // all fits at the tail
tail_bytes = bytes;
wrap_bytes = 0;
}
if (tail_bytes)
{
memcpy (sbuffer + source->sbuf_tail, dec_buf, tail_bytes);
source->sbuf_tail += tail_bytes;
}
if (wrap_bytes)
{
memcpy (sbuffer, dec_buf + tail_bytes, wrap_bytes);
source->sbuf_tail = wrap_bytes;
}
}
static void
process_stream (TFB_SoundSource *source)
{
TFB_SoundSample *sample = source->sample;
TFB_SoundDecoder *decoder = sample->decoder;
bool end_chunk_failed = false;
audio_IntVal processed;
audio_IntVal queued;
audio_GetSourcei (source->handle, audio_BUFFERS_PROCESSED, &processed);
audio_GetSourcei (source->handle, audio_BUFFERS_QUEUED, &queued);
if (processed == 0)
{ // Nothing was played
audio_IntVal state;
audio_GetSourcei (source->handle, audio_SOURCE_STATE, &state);
if (state != audio_PLAYING)
{
if (queued == 0 && decoder->error == SOUNDDECODER_EOF)
{ // The stream has reached the end
log_add (log_Info, "StreamDecoderTaskFunc(): "
"finished playing %s", decoder->filename);
source->stream_should_be_playing = FALSE;
if (sample->callbacks.OnEndStream)
sample->callbacks.OnEndStream (sample);
}
else
{
log_add (log_Warning, "StreamDecoderTaskFunc(): "
"buffer underrun playing %s", decoder->filename);
audio_SourcePlay (source->handle);
}
}
}
// Unqueue processed buffers and replace them with new ones
for (processed; processed > 0; --processed)
{
uint32 error;
audio_Object buffer;
uint32 decoded_bytes;
audio_GetError (); // clear error state
// Get the buffer that finished playing
audio_SourceUnqueueBuffers (source->handle, 1, &buffer);
error = audio_GetError();
if (error != audio_NO_ERROR)
{
log_add (log_Warning, "StreamDecoderTaskFunc(): "
"error after audio_SourceUnqueueBuffers: %x, file %s",
error, decoder->filename);
break;
}
// Process a callback on a tagged buffer, if any
if (sample->callbacks.OnTaggedBuffer)
{
TFB_SoundTag* tag = TFB_FindTaggedBuffer (sample, buffer);
if (tag)
sample->callbacks.OnTaggedBuffer (sample, tag);
}
if (source->sbuffer)
remove_scope_data (source, buffer);
// See what state the decoder was left in last time around
if (decoder->error != SOUNDDECODER_OK)
{
if (decoder->error == SOUNDDECODER_EOF)
{
if (end_chunk_failed)
continue; // should not do it again
if (!sample->callbacks.OnEndChunk ||
!sample->callbacks.OnEndChunk (sample, source->last_q_buf))
{ // Reached the end of the current stream and we did not
// get another sample to play (relevant for Trackplayer)
end_chunk_failed = true;
continue;
}
else
{ // OnEndChunk succeeded, so someone (read: Trackplayer)
// wants to keep going, probably with a new decoder.
// Get the new decoder
decoder = sample->decoder;
}
}
else
{ // Decoder returned a real error, keep going
#if 0
log_add (log_Debug, "StreamDecoderTaskFunc(): "
"decoder->error is %d for %s", decoder->error,
decoder->filename);
#endif
continue;
}
}
// Now replace the unqueued buffer with a new one
decoded_bytes = SoundDecoder_Decode (decoder);
if (decoder->error == SOUNDDECODER_ERROR)
{
log_add (log_Warning, "StreamDecoderTaskFunc(): "
"SoundDecoder_Decode error %d, file %s",
decoder->error, decoder->filename);
source->stream_should_be_playing = FALSE;
continue;
}
if (decoded_bytes == 0)
{ // Nothing was decoded, keep going
continue;
// This loses a stream buffer, which we cannot get back
// w/o restarting the stream, but we should never get here.
}
// And a new buffer is born
audio_BufferData (buffer, decoder->format, decoder->buffer,
decoded_bytes, decoder->frequency);
error = audio_GetError();
if (error != audio_NO_ERROR)
{
log_add (log_Warning, "StreamDecoderTaskFunc(): "
"error after audio_BufferData: %x, file %s, decoded %d",
error, decoder->filename, decoded_bytes);
continue;
}
// Now queue the buffer
audio_SourceQueueBuffers (source->handle, 1, &buffer);
error = audio_GetError();
if (error != audio_NO_ERROR)
{
log_add (log_Warning, "StreamDecoderTaskFunc(): "
"error after audio_SourceQueueBuffers: %x, file %s, "
"decoded %d", error, decoder->filename, decoded_bytes);
continue;
}
// Remember the last queued buffer so we can pass it to callbacks
source->last_q_buf = buffer;
if (sample->callbacks.OnQueueBuffer)
sample->callbacks.OnQueueBuffer (sample, buffer);
if (source->sbuffer)
add_scope_data (source, decoded_bytes);
}
}
int int
StreamDecoderTaskFunc (void *data) StreamDecoderTaskFunc (void *data)
{ {
Task task = (Task)data; Task task = (Task)data;
int i; int i;
audio_Object last_buffer[NUM_SOUNDSOURCES];
for (i = 0; i < NUM_SOUNDSOURCES; i++)
last_buffer[i] = 0;
while (!Task_ReadState (task, TASK_EXIT)) while (!Task_ReadState (task, TASK_EXIT))
{ {
TaskSwitch (); TaskSwitch ();
for (i = MUSIC_SOURCE; i < NUM_SOUNDSOURCES; ++i) for (i = MUSIC_SOURCE; i < NUM_SOUNDSOURCES; ++i)
{ {
audio_IntVal processed, queued; TFB_SoundSource *source = &soundSource[i];
audio_IntVal state;
LockMutex (soundSource[i].stream_mutex); LockMutex (source->stream_mutex);
if (!soundSource[i].sample || if (!source->sample ||
!soundSource[i].sample->decoder || !source->sample->decoder ||
!soundSource[i].stream_should_be_playing || !source->stream_should_be_playing ||
soundSource[i].sample->decoder->error == SOUNDDECODER_ERROR) source->sample->decoder->error == SOUNDDECODER_ERROR)
{ {
UnlockMutex (soundSource[i].stream_mutex); UnlockMutex (source->stream_mutex);
continue; continue;
} }
audio_GetSourcei (soundSource[i].handle, audio_BUFFERS_PROCESSED, process_stream (source);
&processed);
audio_GetSourcei (soundSource[i].handle, audio_BUFFERS_QUEUED,
&queued);
if (processed == 0) UnlockMutex (source->stream_mutex);
{
audio_GetSourcei (soundSource[i].handle, audio_SOURCE_STATE,
&state);
if (state != audio_PLAYING)
{
if (queued == 0 && soundSource[i].sample->decoder->error
== SOUNDDECODER_EOF)
{
log_add (log_Info, "StreamDecoderTaskFunc(): "
"finished playing %s, source %d",
soundSource[i].sample->decoder->filename, i);
soundSource[i].stream_should_be_playing = FALSE;
if (soundSource[i].sample->callbacks.OnEndStream)
soundSource[i].sample->callbacks.OnEndStream (
soundSource[i].sample);
}
else
{
log_add (log_Warning, "StreamDecoderTaskFunc(): buffer "
"underrun when playing %s, source %d",
soundSource[i].sample->decoder->filename, i);
audio_SourcePlay (soundSource[i].handle);
}
}
}
#if 0
log_add (log_Debug, "StreamDecoderTaskFunc(): source %d, processed %d queued %d",
i, processed, queued);
#endif
while (processed)
{
uint32 error;
audio_Object buffer;
uint32 decoded_bytes;
audio_GetError (); // clear error state
audio_SourceUnqueueBuffers (soundSource[i].handle, 1, &buffer);
error = audio_GetError();
if (error != audio_NO_ERROR)
{
log_add (log_Warning, "StreamDecoderTaskFunc(): OpenAL "
"error after alSourceUnqueueBuffers: %x, "
"file %s, source %d", error,
soundSource[i].sample->decoder->filename, i);
break;
}
if (soundSource[i].sample->callbacks.OnTaggedBuffer)
{
TFB_SoundTag* tag = TFB_FindTaggedBuffer (
soundSource[i].sample, buffer);
if (tag)
{
soundSource[i].sample->callbacks.OnTaggedBuffer (
soundSource[i].sample, tag);
}
}
{
audio_IntVal buf_size;
soundSource[i].sbuf_lasttime = GetTimeCounter ();
audio_GetBufferi(buffer, audio_SIZE, &buf_size);
soundSource[i].sbuf_offset += buf_size;
if (soundSource[i].sbuf_offset > soundSource[i].sbuf_size)
soundSource[i].sbuf_offset -=
soundSource[i].sbuf_size;
}
//soundSource[i].total_decoded += soundSource[i].sample->decoder->buffer_size;
if (soundSource[i].sample->decoder->error)
{
if (soundSource[i].sample->decoder->error ==
SOUNDDECODER_EOF)
{
if (!soundSource[i].sample->callbacks.OnEndChunk ||
!soundSource[i].sample->callbacks.OnEndChunk (
soundSource[i].sample, last_buffer[i]))
{
#if 0
log_add (log_Debug, "StreamDecoderTaskFunc(): decoder->error is eof for %s",
soundSource[i].sample->decoder->filename);
#endif
processed--;
continue;
}
}
else
{
#if 0
log_add (log_Debug, "StreamDecoderTaskFunc(): decoder->error is %d for %s",
soundSource[i].sample->decoder->error,
soundSource[i].sample->decoder->filename);
#endif
processed--;
continue;
}
}
decoded_bytes = SoundDecoder_Decode (
soundSource[i].sample->decoder);
if (soundSource[i].sample->decoder->error ==
SOUNDDECODER_ERROR)
{
log_add (log_Warning, "StreamDecoderTaskFunc(): "
"SoundDecoder_Decode error %d, file %s, "
"source %d",
soundSource[i].sample->decoder->error,
soundSource[i].sample->decoder->filename, i);
soundSource[i].stream_should_be_playing = FALSE;
processed--;
continue;
}
if (decoded_bytes > 0)
{
audio_BufferData (buffer,
soundSource[i].sample->decoder->format,
soundSource[i].sample->decoder->buffer,
decoded_bytes,
soundSource[i].sample->decoder->frequency);
error = audio_GetError();
if (error != audio_NO_ERROR)
{
log_add (log_Warning, "StreamDecoderTaskFunc(): "
"TFBSound error after audio_BufferData: "
"%x, file %s, source %d, decoded_bytes %d",
error, soundSource[i].sample->decoder->filename,
i, decoded_bytes);
}
else
{
last_buffer[i] = buffer;
audio_SourceQueueBuffers (soundSource[i].handle, 1,
&buffer);
// do OnQueue callback
if (soundSource[i].sample->callbacks.OnQueueBuffer)
soundSource[i].sample->callbacks.OnQueueBuffer (
soundSource[i].sample, buffer);
if (soundSource[i].sbuffer)
{
// copies decoded data to oscilloscope buffer
uint32 j, remaining_bytes = 0;
UBYTE *sbuffer = (UBYTE *) soundSource[i].sbuffer;
UBYTE *decoder_buffer = (UBYTE *) soundSource[i].
sample->decoder->buffer;
if (soundSource[i].sbuf_start + decoded_bytes >
soundSource[i].sbuf_size)
{
j = soundSource[i].sbuf_size;
remaining_bytes = decoded_bytes -
(j - soundSource[i].sbuf_start);
}
else
{
j = soundSource[i].sbuf_start + decoded_bytes;
}
if (j - soundSource[i].sbuf_start >= 1)
{
memcpy (&sbuffer[soundSource[i].sbuf_start],
decoder_buffer,
j - soundSource[i].sbuf_start);
}
if (remaining_bytes)
{
memcpy (sbuffer, &decoder_buffer[
j - soundSource[i].sbuf_start],
remaining_bytes);
soundSource[i].sbuf_start = remaining_bytes;
}
else
{
soundSource[i].sbuf_start += decoded_bytes;
}
}
error = audio_GetError();
if (error != audio_NO_ERROR)
{
log_add (log_Warning, "StreamDecoderTaskFunc(): "
"TFBSound error after "
"audio_SourceQueueBuffers: %x, file %s, "
"source %d, decoded_bytes %d", error,
soundSource[i].sample->decoder->filename,
i, decoded_bytes);
}
}
}
processed--;
}
UnlockMutex (soundSource[i].stream_mutex);
} }
} }
@@ -582,7 +643,7 @@ GraphForegroundStream (uint8 *data, sint32 width, sint32 height)
step *= full_sample; step *= full_sample;
sbuffer = source->sbuffer; sbuffer = source->sbuffer;
pos = source->sbuf_offset + delta; pos = source->sbuf_head + delta;
// We are not basing the scaling factor on signal energy, because we // We are not basing the scaling factor on signal energy, because we
// want it to *look* pretty instead of sounding nice and even // want it to *look* pretty instead of sounding nice and even
-4
View File
@@ -26,10 +26,6 @@ void SeekStream (uint32 source, uint32 pos);
BOOLEAN PlayingStream (uint32 source); BOOLEAN PlayingStream (uint32 source);
int StreamDecoderTaskFunc (void *data); int StreamDecoderTaskFunc (void *data);
TFB_SoundTag* FindTaggedBuffer (TFB_SoundSample* sample, audio_Object buffer);
void TFB_ClearBufferTag (TFB_SoundTag* ptag);
void TFB_TagBuffer (TFB_SoundSample* sample, audio_Object buffer, void* data);
int GraphForegroundStream (uint8 *data, sint32 width, sint32 height); int GraphForegroundStream (uint8 *data, sint32 width, sint32 height);
#endif #endif
+8 -23
View File
@@ -15,6 +15,7 @@
*/ */
#include "sound.h" #include "sound.h"
#include "sndintrn.h"
#include "libs/sound/trackplayer.h" #include "libs/sound/trackplayer.h"
#include "trackint.h" #include "trackint.h"
#include "libs/log.h" #include "libs/log.h"
@@ -54,7 +55,6 @@ static TFB_SoundChunk *cur_sub_chunk; // currently displayed subtitle chunk
// structures the same way. // structures the same way.
static void seek_track (sint32 offset); static void seek_track (sint32 offset);
static void destroy_SoundSample (TFB_SoundSample *sample);
// stream callbacks // stream callbacks
static bool OnStreamStart (TFB_SoundSample* sample); static bool OnStreamStart (TFB_SoundSample* sample);
@@ -190,7 +190,9 @@ StopTrack (void)
} }
if (sound_sample) if (sound_sample)
{ {
destroy_SoundSample (sound_sample); // We delete the decoders ourselves
sound_sample->decoder = NULL;
TFB_DestroySoundSample (sound_sample);
sound_sample = NULL; sound_sample = NULL;
} }
} }
@@ -250,7 +252,7 @@ OnChunkEnd (TFB_SoundSample* sample, audio_Object buffer)
if (cur_chunk->tag_me) if (cur_chunk->tag_me)
{ // Tag the last buffer of the chunk with the next chunk { // Tag the last buffer of the chunk with the next chunk
TFB_TagBuffer (sample, buffer, cur_chunk); TFB_TagBuffer (sample, buffer, (intptr_t)cur_chunk);
} }
return true; return true;
@@ -276,6 +278,8 @@ OnBufferTag (TFB_SoundSample* sample, TFB_SoundTag* tag)
{ {
TFB_SoundChunk* chunk = (TFB_SoundChunk*) tag->data; TFB_SoundChunk* chunk = (TFB_SoundChunk*) tag->data;
assert (sizeof (tag->data) >= sizeof (chunk));
if (sample != sound_sample) if (sample != sound_sample)
return; // Huh? Why did we get called on this? return; // Huh? Why did we get called on this?
@@ -562,13 +566,7 @@ SpliceTrack (UNICODE *TrackName, UNICODE *TrackText, UNICODE *TimeStamp, TFB_Tra
if (!sound_sample) if (!sound_sample)
{ {
sound_sample = HCalloc (sizeof (*sound_sample)); sound_sample = TFB_CreateSoundSample (NULL, 8, &trackCBs);
sound_sample->callbacks = trackCBs;
sound_sample->num_buffers = 8;
sound_sample->buffer_tag = HCalloc (sizeof (TFB_SoundTag) * sound_sample->num_buffers);
sound_sample->buffer = HCalloc (sizeof (audio_Object) * sound_sample->num_buffers);
sound_sample->length = 0;
audio_GenBuffers (sound_sample->num_buffers, sound_sample->buffer);
chunks_head = create_SoundChunk (decoder, 0.0); chunks_head = create_SoundChunk (decoder, 0.0);
chunks_tail = chunks_head; chunks_tail = chunks_head;
} }
@@ -800,19 +798,6 @@ destroy_SoundChunk_list (TFB_SoundChunk *chunk)
} }
} }
static void
destroy_SoundSample (TFB_SoundSample *sample)
{
if (sample->buffer)
{
audio_DeleteBuffers (sample->num_buffers, sample->buffer);
HFree (sample->buffer);
}
HFree (sample->buffer_tag);
HFree (sample->data);
HFree (sample);
}
// Returns the next chunk with a subtitle // Returns the next chunk with a subtitle
TFB_SoundChunk * TFB_SoundChunk *
find_next_page (TFB_SoundChunk *cur) find_next_page (TFB_SoundChunk *cur)
+25 -21
View File
@@ -31,7 +31,7 @@ static uint32 vp_GetTicks (TFB_VideoDecoder*);
static bool vp_SetTimer (TFB_VideoDecoder*, uint32 msecs); static bool vp_SetTimer (TFB_VideoDecoder*, uint32 msecs);
TFB_VideoCallbacks vp_DecoderCBs = static const TFB_VideoCallbacks vp_DecoderCBs =
{ {
vp_BeginFrame, vp_BeginFrame,
vp_EndFrame, vp_EndFrame,
@@ -46,7 +46,7 @@ static void vp_AudioEnd (TFB_SoundSample* sample);
static void vp_BufferTag (TFB_SoundSample* sample, TFB_SoundTag* tag); static void vp_BufferTag (TFB_SoundSample* sample, TFB_SoundTag* tag);
static void vp_QueueBuffer (TFB_SoundSample* sample, audio_Object buffer); static void vp_QueueBuffer (TFB_SoundSample* sample, audio_Object buffer);
static TFB_SoundCallbacks vp_AudioCBs = static const TFB_SoundCallbacks vp_AudioCBs =
{ {
vp_AudioStart, vp_AudioStart,
NULL, NULL,
@@ -307,8 +307,6 @@ TFB_PlayVideo (VIDEO_REF vid, uint32 x, uint32 y)
if (vid->decoder->audio_synced) if (vid->decoder->audio_synced)
{ {
TFB_SoundSample **pmus;
if (!vid->hAudio) if (!vid->hAudio)
{ {
log_add (log_Warning, "TFB_PlayVideo: " log_add (log_Warning, "TFB_PlayVideo: "
@@ -316,12 +314,8 @@ TFB_PlayVideo (VIDEO_REF vid, uint32 x, uint32 y)
return false; return false;
} }
// nasty hack for now TFB_SetSoundSampleCallbacks (*vid->hAudio, &vp_AudioCBs);
pmus = vid->hAudio; TFB_SetSoundSampleData (*vid->hAudio, (intptr_t)vid);
(*pmus)->buffer_tag = HCalloc (
sizeof (TFB_SoundTag) * (*pmus)->num_buffers);
(*pmus)->callbacks = vp_AudioCBs;
(*pmus)->data = vid; // hijack data ;)
} }
SetSemaphore (vp_interthread_lock); SetSemaphore (vp_interthread_lock);
@@ -406,9 +400,7 @@ TFB_SeekVideo (VIDEO_REF vid, uint32 pos)
if (vid->decoder->audio_synced) if (vid->decoder->audio_synced)
{ {
LockMutex (soundSource[MUSIC_SOURCE].stream_mutex); PLRSeek (vid->hAudio, pos);
SeekStream (MUSIC_SOURCE, pos);
UnlockMutex (soundSource[MUSIC_SOURCE].stream_mutex);
TaskSwitch (); TaskSwitch ();
return true; return true;
} }
@@ -475,10 +467,16 @@ vp_SetTimer (TFB_VideoDecoder* decoder, uint32 msecs)
static bool static bool
vp_AudioStart (TFB_SoundSample* sample) vp_AudioStart (TFB_SoundSample* sample)
{ {
TFB_VideoClip* vid = sample->data; TFB_VideoClip* vid = (TFB_VideoClip*) TFB_GetSoundSampleData (sample);
TFB_SoundDecoder *decoder;
assert (sizeof (intptr_t) >= sizeof (vid));
assert (vid != NULL);
decoder = TFB_GetSoundSampleDecoder (sample);
LockMutex (vid->guard); LockMutex (vid->guard);
vid->want_frame = SoundDecoder_GetFrame (sample->decoder); vid->want_frame = SoundDecoder_GetFrame (decoder);
UnlockMutex (vid->guard); UnlockMutex (vid->guard);
return true; return true;
@@ -487,7 +485,9 @@ vp_AudioStart (TFB_SoundSample* sample)
static void static void
vp_AudioEnd (TFB_SoundSample* sample) vp_AudioEnd (TFB_SoundSample* sample)
{ {
TFB_VideoClip* vid = sample->data; TFB_VideoClip* vid = (TFB_VideoClip*) TFB_GetSoundSampleData (sample);
assert (vid != NULL);
LockMutex (vid->guard); LockMutex (vid->guard);
vid->want_frame = vid->decoder->frame_count; // end it vid->want_frame = vid->decoder->frame_count; // end it
@@ -497,9 +497,12 @@ vp_AudioEnd (TFB_SoundSample* sample)
static void static void
vp_BufferTag (TFB_SoundSample* sample, TFB_SoundTag* tag) vp_BufferTag (TFB_SoundSample* sample, TFB_SoundTag* tag)
{ {
TFB_VideoClip* vid = sample->data; TFB_VideoClip* vid = (TFB_VideoClip*) TFB_GetSoundSampleData (sample);
uint32 frame = (uint32) (intptr_t) tag->data; uint32 frame = (uint32) tag->data;
assert (sizeof (tag->data) >= sizeof (frame));
assert (vid != NULL);
LockMutex (vid->guard); LockMutex (vid->guard);
vid->want_frame = frame; // let it go! vid->want_frame = frame; // let it go!
UnlockMutex (vid->guard); UnlockMutex (vid->guard);
@@ -508,9 +511,10 @@ vp_BufferTag (TFB_SoundSample* sample, TFB_SoundTag* tag)
static void static void
vp_QueueBuffer (TFB_SoundSample* sample, audio_Object buffer) vp_QueueBuffer (TFB_SoundSample* sample, audio_Object buffer)
{ {
//TFB_VideoClip* vid = sample->data; //TFB_VideoClip* vid = (TFB_VideoClip*) TFB_GetSoundSampleData (sample);
TFB_SoundDecoder *decoder = TFB_GetSoundSampleDecoder (sample);
TFB_TagBuffer (sample, buffer, TFB_TagBuffer (sample, buffer,
(void *) (intptr_t) SoundDecoder_GetFrame (sample->decoder)); (intptr_t) SoundDecoder_GetFrame (decoder));
} }
+2 -2
View File
@@ -90,8 +90,8 @@ PlaySoundEffect (SOUND S, COUNT Channel, SoundPosition Pos,
if (!(GLOBAL (glob_flags) & SOUND_DISABLED)) if (!(GLOBAL (glob_flags) & SOUND_DISABLED))
{ {
SetChannelVolume (Channel, MAX_VOLUME >> 1, Priority); SetChannelVolume (Channel, MAX_VOLUME >> 1, Priority);
SetChannelRate (Channel, GetSampleRate (S), Priority); //SetChannelRate (Channel, GetSampleRate (S), Priority);
PlayChannel (Channel, GetSampleAddress (S), Pos, PositionalObject, Priority); PlayChannel (Channel, S, Pos, PositionalObject, Priority);
} }
} }