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:
@@ -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 */
|
||||||
|
|||||||
@@ -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 ||
|
||||||
|
|||||||
@@ -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,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
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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
@@ -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
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user