merge mixsdl and openal decoders. This removes a lot of duplicate code,
and should make maintenance a lot easier git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@605 8092fc87-c524-0410-9efc-e669fe64eaf9
This commit is contained in:
@@ -9,5 +9,5 @@ else
|
|||||||
uqm_CFLAGS="$uqm_CFLAGS -DSOUNDMODULE_SDL"
|
uqm_CFLAGS="$uqm_CFLAGS -DSOUNDMODULE_SDL"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
uqm_CFILES="fileinst.c resinst.c sound_common.c"
|
uqm_CFILES="fileinst.c resinst.c sound_common.c sound.c sfx.c music.c stream.c trackplayer.c"
|
||||||
|
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
uqm_CFILES="mixer.c sound.c music.c sfx.c stream.c trackplayer.c"
|
uqm_CFILES="mixer.c sound_mixsdl.c"
|
||||||
|
|||||||
+2
-118
@@ -17,12 +17,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef SOUNDMODULE_MIXSDL
|
#ifdef SOUNDMODULE_MIXSDL
|
||||||
|
|
||||||
#include "libs/graphics/sdl/sdl_common.h"
|
#include "libs/graphics/sdl/sdl_common.h"
|
||||||
#include "libs/sound/sound_common.h"
|
#include "libs/sound/sound.h"
|
||||||
#include "sound.h"
|
|
||||||
|
|
||||||
TFB_SoundSource soundSource[NUM_SOUNDSOURCES];
|
|
||||||
static Task StreamDecoderTask;
|
static Task StreamDecoderTask;
|
||||||
|
|
||||||
int
|
int
|
||||||
@@ -134,116 +130,4 @@ TFB_UninitSound (void)
|
|||||||
mixSDL_CloseAudio ();
|
mixSDL_CloseAudio ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
#endif
|
||||||
StopSound (void)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = FIRST_SFX_SOURCE; i <= LAST_SFX_SOURCE; ++i)
|
|
||||||
{
|
|
||||||
mixSDL_SourceRewind (soundSource[i].handle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOLEAN
|
|
||||||
SoundPlaying (void)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < NUM_SOUNDSOURCES; ++i)
|
|
||||||
{
|
|
||||||
TFB_SoundSample *sample;
|
|
||||||
sample = soundSource[i].sample;
|
|
||||||
if (sample && sample->decoder)
|
|
||||||
{
|
|
||||||
BOOLEAN result;
|
|
||||||
LockMutex (soundSource[i].stream_mutex);
|
|
||||||
result = PlayingStream (i);
|
|
||||||
UnlockMutex (soundSource[i].stream_mutex);
|
|
||||||
if (result)
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
uint32 state;
|
|
||||||
mixSDL_GetSourcei (soundSource[i].handle, MIX_SOURCE_STATE, &state);
|
|
||||||
if (state == MIX_PLAYING)
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
TFB_SoundChain *
|
|
||||||
create_soundchain (TFB_SoundDecoder *decoder, float startTime)
|
|
||||||
{
|
|
||||||
TFB_SoundChain *chain;
|
|
||||||
chain = (TFB_SoundChain *)HMalloc (sizeof (TFB_SoundChain));
|
|
||||||
chain->decoder = decoder;
|
|
||||||
chain->next =NULL;
|
|
||||||
chain->start_time = startTime;
|
|
||||||
chain->tag.buf_name = 0;
|
|
||||||
chain->tag.type = 0;
|
|
||||||
return (chain);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
destroy_soundchain (TFB_SoundChain *chain)
|
|
||||||
{
|
|
||||||
while (chain->next)
|
|
||||||
{
|
|
||||||
TFB_SoundChain *tmp_chain = chain->next;
|
|
||||||
chain->next = chain->next->next;
|
|
||||||
if (tmp_chain->decoder)
|
|
||||||
SoundDecoder_Free (tmp_chain->decoder);
|
|
||||||
HFree (tmp_chain);
|
|
||||||
}
|
|
||||||
SoundDecoder_Free (chain->decoder);
|
|
||||||
HFree (chain);
|
|
||||||
}
|
|
||||||
|
|
||||||
TFB_SoundChain *
|
|
||||||
get_previous_chain (TFB_SoundChain *first_chain, TFB_SoundChain *current_chain)
|
|
||||||
{
|
|
||||||
TFB_SoundChain *prev_chain;
|
|
||||||
prev_chain = first_chain;
|
|
||||||
if (prev_chain == current_chain)
|
|
||||||
return (prev_chain);
|
|
||||||
while (prev_chain->next)
|
|
||||||
{
|
|
||||||
if (prev_chain->next == current_chain)
|
|
||||||
return (prev_chain);
|
|
||||||
prev_chain = prev_chain->next;
|
|
||||||
}
|
|
||||||
return (first_chain);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Status: Ignored
|
|
||||||
BOOLEAN
|
|
||||||
InitSound (int argc, char* argv[])
|
|
||||||
{
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Status: Ignored
|
|
||||||
void
|
|
||||||
UninitSound (void)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetSFXVolume (float volume)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
for (i = FIRST_SFX_SOURCE; i <= LAST_SFX_SOURCE; ++i)
|
|
||||||
{
|
|
||||||
mixSDL_Sourcef (soundSource[i].handle, MIX_GAIN, volume);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetSpeechVolume (float volume)
|
|
||||||
{
|
|
||||||
mixSDL_Sourcef (soundSource[SPEECH_SOURCE].handle, MIX_GAIN, volume);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* OpenAL specific code by Mika Kolehmainen, 2002-10-23
|
||||||
|
*/
|
||||||
|
#include "mixer.h"
|
||||||
|
|
||||||
|
#define TFBSound_Object mixSDL_Object
|
||||||
|
|
||||||
|
/*************************************************
|
||||||
|
* General interface
|
||||||
|
*/
|
||||||
|
#define TFBSound_GetError mixSDL_GetError
|
||||||
|
#define TFBSound_OpenAudio mixSDL_OpenAudio
|
||||||
|
#define TFBSound_CloseAudio mixSDL_CloseAudio
|
||||||
|
#define TFBSound_QuerySpec mixSDL_QuerySpec
|
||||||
|
|
||||||
|
/*************************************************
|
||||||
|
* Sources
|
||||||
|
*/
|
||||||
|
#define TFBSound_GenSources mixSDL_GenSources
|
||||||
|
#define TFBSound_DeleteSources mixSDL_DeleteSources
|
||||||
|
#define TFBSound_IsSource mixSDL_IsSource
|
||||||
|
#define TFBSound_Sourcei mixSDL_Sourcei
|
||||||
|
#define TFBSound_Sourcef mixSDL_Sourcef
|
||||||
|
#define TFBSound_GetSourcei mixSDL_GetSourcei
|
||||||
|
#define TFBSound_GetSourcef mixSDL_GetSourcef
|
||||||
|
#define TFBSound_SourceRewind mixSDL_SourceRewind
|
||||||
|
#define TFBSound_SourcePlay mixSDL_SourcePlay
|
||||||
|
#define TFBSound_SourcePause mixSDL_SourcePause
|
||||||
|
#define TFBSound_SourceStop mixSDL_SourceStop
|
||||||
|
#define TFBSound_SourceQueueBuffers mixSDL_SourceQueueBuffers
|
||||||
|
#define TFBSound_SourceUnqueueBuffers mixSDL_SourceUnqueueBuffers
|
||||||
|
|
||||||
|
/*************************************************
|
||||||
|
* Buffers
|
||||||
|
*/
|
||||||
|
#define TFBSound_GenBuffers mixSDL_GenBuffers
|
||||||
|
#define TFBSound_DeleteBuffers mixSDL_DeleteBuffers
|
||||||
|
#define TFBSound_IsBuffer mixSDL_IsBuffer
|
||||||
|
#define TFBSound_GetBufferi mixSDL_GetBufferi
|
||||||
|
#define TFBSound_BufferData mixSDL_BufferData
|
||||||
|
#define TFBSound_ConvertBuffer mixSDL_ConvertBuffer
|
||||||
|
|
||||||
|
#define TFBSOUND_GAIN MIX_GAIN
|
||||||
|
#define TFBSOUND_BUFFER MIX_BUFFER
|
||||||
|
#define TFBSOUND_SOURCE_STATE MIX_SOURCE_STATE
|
||||||
|
#define TFBSOUND_PLAYING MIX_PLAYING
|
||||||
|
#define TFBSOUND_PAUSED MIX_PAUSED
|
||||||
|
#define TFBSOUND_FORMAT_MONO16 MIX_FORMAT_MONO16
|
||||||
|
#define TFBSOUND_FORMAT_STEREO16 MIX_FORMAT_STEREO16
|
||||||
|
#define TFBSOUND_FORMAT_STEREO8 MIX_FORMAT_STEREO8
|
||||||
|
#define TFBSOUND_LOOPING MIX_LOOPING
|
||||||
|
#define TFBSOUND_BUFFERS_PROCESSED MIX_BUFFERS_PROCESSED
|
||||||
|
#define TFBSOUND_BUFFERS_QUEUED MIX_BUFFERS_QUEUED
|
||||||
|
#define TFBSOUND_NO_ERROR MIX_NO_ERROR
|
||||||
|
#define TFBSOUND_SIZE MIX_SIZE
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
/* OpenAL specific code by Mika Kolehmainen, 2002-10-23
|
/* OpenAL specific code by Mika Kolehmainen, 2002-10-23
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef SOUNDMODULE_MIXSDL
|
#if defined SOUNDMODULE_MIXSDL || defined SOUNDMODULE_OPENAL
|
||||||
|
|
||||||
#include "sound.h"
|
#include "sound.h"
|
||||||
#include "options.h"
|
#include "options.h"
|
||||||
@@ -108,7 +108,7 @@ SetMusicVolume (COUNT Volume)
|
|||||||
{
|
{
|
||||||
float f = (Volume / (float)MAX_VOLUME) * musicVolumeScale;
|
float f = (Volume / (float)MAX_VOLUME) * musicVolumeScale;
|
||||||
musicVolume = Volume;
|
musicVolume = Volume;
|
||||||
mixSDL_Sourcef (soundSource[MUSIC_SOURCE].handle, MIX_GAIN, f);
|
TFBSound_Sourcef (soundSource[MUSIC_SOURCE].handle, TFBSOUND_GAIN, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
MEM_HANDLE
|
MEM_HANDLE
|
||||||
@@ -174,8 +174,8 @@ _GetMusicData (FILE *fp, DWORD length)
|
|||||||
(*pmus)->decoder->frequency, (*pmus)->decoder->format);
|
(*pmus)->decoder->frequency, (*pmus)->decoder->format);
|
||||||
|
|
||||||
(*pmus)->num_buffers = 64;
|
(*pmus)->num_buffers = 64;
|
||||||
(*pmus)->buffer = (mixSDL_Object *) HMalloc (sizeof (mixSDL_Object) * (*pmus)->num_buffers);
|
(*pmus)->buffer = (TFBSound_Object *) HMalloc (sizeof (TFBSound_Object) * (*pmus)->num_buffers);
|
||||||
mixSDL_GenBuffers ((*pmus)->num_buffers, (*pmus)->buffer);
|
TFBSound_GenBuffers ((*pmus)->num_buffers, (*pmus)->buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -208,7 +208,7 @@ _ReleaseMusicData (MEM_HANDLE handle)
|
|||||||
|
|
||||||
(*pmus)->decoder = NULL;
|
(*pmus)->decoder = NULL;
|
||||||
SoundDecoder_Free (decoder);
|
SoundDecoder_Free (decoder);
|
||||||
mixSDL_DeleteBuffers ((*pmus)->num_buffers, (*pmus)->buffer);
|
TFBSound_DeleteBuffers ((*pmus)->num_buffers, (*pmus)->buffer);
|
||||||
HFree ((*pmus)->buffer);
|
HFree ((*pmus)->buffer);
|
||||||
}
|
}
|
||||||
HFree (*pmus);
|
HFree (*pmus);
|
||||||
@@ -1 +1 @@
|
|||||||
uqm_CFILES="music.c sfx.c sound.c stream.c trackplayer.c"
|
uqm_CFILES="sound_openal.c"
|
||||||
|
|||||||
@@ -1,223 +0,0 @@
|
|||||||
/*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* OpenAL specific code by Mika Kolehmainen, 2002-10-23
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef SOUNDMODULE_OPENAL
|
|
||||||
|
|
||||||
#include "sound.h"
|
|
||||||
#include "options.h"
|
|
||||||
#include "file.h"
|
|
||||||
|
|
||||||
static MUSIC_REF curMusicRef;
|
|
||||||
|
|
||||||
void
|
|
||||||
PLRPlaySong (MUSIC_REF MusicRef, BOOLEAN Continuous, BYTE Priority)
|
|
||||||
{
|
|
||||||
TFB_SoundSample **pmus;
|
|
||||||
|
|
||||||
LockMusicData (MusicRef, &pmus);
|
|
||||||
if (pmus)
|
|
||||||
{
|
|
||||||
LockMutex (soundSource[MUSIC_SOURCE].stream_mutex);
|
|
||||||
PlayStream ((*pmus), MUSIC_SOURCE, Continuous,
|
|
||||||
speechVolumeScale == 0.0f ? AL_TRUE : AL_FALSE,
|
|
||||||
AL_TRUE);
|
|
||||||
UnlockMutex (soundSource[MUSIC_SOURCE].stream_mutex);
|
|
||||||
|
|
||||||
curMusicRef = MusicRef;
|
|
||||||
}
|
|
||||||
|
|
||||||
(void) Priority; /* Satisfy compiler because of unused variable */
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PLRStop (MUSIC_REF MusicRef)
|
|
||||||
{
|
|
||||||
if (MusicRef == curMusicRef || MusicRef == (MUSIC_REF)~0)
|
|
||||||
{
|
|
||||||
LockMutex (soundSource[MUSIC_SOURCE].stream_mutex);
|
|
||||||
StopStream (MUSIC_SOURCE);
|
|
||||||
UnlockMutex (soundSource[MUSIC_SOURCE].stream_mutex);
|
|
||||||
UnlockMusicData (curMusicRef);
|
|
||||||
|
|
||||||
curMusicRef = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOLEAN
|
|
||||||
PLRPlaying (MUSIC_REF MusicRef)
|
|
||||||
{
|
|
||||||
if (curMusicRef && (MusicRef == curMusicRef || MusicRef == (MUSIC_REF)~0))
|
|
||||||
{
|
|
||||||
BOOLEAN playing;
|
|
||||||
|
|
||||||
LockMutex (soundSource[MUSIC_SOURCE].stream_mutex);
|
|
||||||
playing = PlayingStream (MUSIC_SOURCE);
|
|
||||||
UnlockMutex (soundSource[MUSIC_SOURCE].stream_mutex);
|
|
||||||
|
|
||||||
return playing;
|
|
||||||
}
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PLRPause (MUSIC_REF MusicRef)
|
|
||||||
{
|
|
||||||
if (MusicRef == curMusicRef || MusicRef == (MUSIC_REF)~0)
|
|
||||||
{
|
|
||||||
LockMutex (soundSource[MUSIC_SOURCE].stream_mutex);
|
|
||||||
PauseStream (MUSIC_SOURCE);
|
|
||||||
UnlockMutex (soundSource[MUSIC_SOURCE].stream_mutex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PLRResume (MUSIC_REF MusicRef)
|
|
||||||
{
|
|
||||||
if (MusicRef == curMusicRef || MusicRef == (MUSIC_REF)~0)
|
|
||||||
{
|
|
||||||
LockMutex (soundSource[MUSIC_SOURCE].stream_mutex);
|
|
||||||
ResumeStream (MUSIC_SOURCE);
|
|
||||||
UnlockMutex (soundSource[MUSIC_SOURCE].stream_mutex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOLEAN
|
|
||||||
DestroyMusic (MUSIC_REF MusicRef)
|
|
||||||
{
|
|
||||||
return (FreeMusicData (MusicRef));
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
SetMusicVolume (COUNT Volume)
|
|
||||||
{
|
|
||||||
float f = (Volume / (ALfloat)MAX_VOLUME) * musicVolumeScale;
|
|
||||||
musicVolume = Volume;
|
|
||||||
alSourcef (soundSource[MUSIC_SOURCE].handle, AL_GAIN, f);
|
|
||||||
}
|
|
||||||
|
|
||||||
MEM_HANDLE
|
|
||||||
_GetMusicData (FILE *fp, DWORD length)
|
|
||||||
{
|
|
||||||
MEM_HANDLE h;
|
|
||||||
extern char *_cur_resfile_name;
|
|
||||||
|
|
||||||
h = 0;
|
|
||||||
if (_cur_resfile_name && (h = AllocMusicData (sizeof (void *))))
|
|
||||||
{
|
|
||||||
TFB_SoundSample **pmus;
|
|
||||||
|
|
||||||
LockMusicData (h, &pmus);
|
|
||||||
if (!pmus)
|
|
||||||
{
|
|
||||||
UnlockMusicData (h);
|
|
||||||
mem_release (h);
|
|
||||||
h = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
char filename[1000];
|
|
||||||
|
|
||||||
*pmus = (TFB_SoundSample *) HMalloc (sizeof (TFB_SoundSample));
|
|
||||||
(*pmus)->buffer_tag = 0;
|
|
||||||
(*pmus)->read_chain_ptr = NULL;
|
|
||||||
strcpy (filename, _cur_resfile_name);
|
|
||||||
|
|
||||||
switch (optWhichMusic)
|
|
||||||
{
|
|
||||||
default:
|
|
||||||
case OPT_3DO:
|
|
||||||
{
|
|
||||||
char threedoname[1000];
|
|
||||||
|
|
||||||
strcpy (threedoname, filename);
|
|
||||||
strcpy (&threedoname[strlen (threedoname)-3], "ogg");
|
|
||||||
if (fileExists (threedoname))
|
|
||||||
{
|
|
||||||
strcpy (filename, threedoname);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case OPT_PC:
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf (stderr, "_GetMusicData(): loading %s\n", filename);
|
|
||||||
if (((*pmus)->decoder = SoundDecoder_Load (filename, 4096, 0, 0)) == 0)
|
|
||||||
{
|
|
||||||
fprintf (stderr, "_GetMusicData(): couldn't load %s\n", filename);
|
|
||||||
|
|
||||||
UnlockMusicData (h);
|
|
||||||
mem_release (h);
|
|
||||||
h = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fprintf (stderr, " decoder: %s, rate %d format %x\n", (*pmus)->decoder->decoder_info,
|
|
||||||
(*pmus)->decoder->frequency, (*pmus)->decoder->format);
|
|
||||||
|
|
||||||
(*pmus)->num_buffers = 64;
|
|
||||||
(*pmus)->buffer = (ALuint *) HMalloc (sizeof (ALuint) * (*pmus)->num_buffers);
|
|
||||||
alGenBuffers ((*pmus)->num_buffers, (*pmus)->buffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
UnlockMusicData (h);
|
|
||||||
}
|
|
||||||
|
|
||||||
(void) fp; /* satisfy compiler (unused parameter) */
|
|
||||||
(void) length; /* satisfy compiler (unused parameter) */
|
|
||||||
return (h);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOLEAN
|
|
||||||
_ReleaseMusicData (MEM_HANDLE handle)
|
|
||||||
{
|
|
||||||
TFB_SoundSample **pmus;
|
|
||||||
|
|
||||||
LockMusicData (handle, &pmus);
|
|
||||||
if (pmus == 0)
|
|
||||||
return (FALSE);
|
|
||||||
|
|
||||||
if ((*pmus)->decoder)
|
|
||||||
{
|
|
||||||
TFB_SoundDecoder *decoder = (*pmus)->decoder;
|
|
||||||
LockMutex (soundSource[MUSIC_SOURCE].stream_mutex);
|
|
||||||
if (soundSource[MUSIC_SOURCE].sample == (*pmus))
|
|
||||||
{
|
|
||||||
StopStream (MUSIC_SOURCE);
|
|
||||||
}
|
|
||||||
UnlockMutex (soundSource[MUSIC_SOURCE].stream_mutex);
|
|
||||||
|
|
||||||
(*pmus)->decoder = NULL;
|
|
||||||
SoundDecoder_Free (decoder);
|
|
||||||
alDeleteBuffers ((*pmus)->num_buffers, (*pmus)->buffer);
|
|
||||||
HFree ((*pmus)->buffer);
|
|
||||||
}
|
|
||||||
HFree (*pmus);
|
|
||||||
|
|
||||||
UnlockMusicData (handle);
|
|
||||||
mem_release (handle);
|
|
||||||
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,267 +0,0 @@
|
|||||||
/*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* OpenAL specific code by Mika Kolehmainen, 2002-10-23
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef SOUNDMODULE_OPENAL
|
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
#include <io.h>
|
|
||||||
#endif
|
|
||||||
#include <fcntl.h>
|
|
||||||
|
|
||||||
#include "sound.h"
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
PlayChannel (COUNT channel, PVOID sample, COUNT sample_length, COUNT loop_begin,
|
|
||||||
COUNT loop_length, unsigned char priority)
|
|
||||||
{
|
|
||||||
TFB_SoundSample *tfb_sample = *(TFB_SoundSample**) sample;
|
|
||||||
soundSource[channel].sample = tfb_sample;
|
|
||||||
alSourceRewind (soundSource[channel].handle);
|
|
||||||
alSourcei (soundSource[channel].handle, AL_BUFFER, tfb_sample->buffer[0]);
|
|
||||||
alSourcePlay (soundSource[channel].handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
StopChannel(COUNT channel, unsigned char Priority)
|
|
||||||
{
|
|
||||||
alSourceRewind (soundSource[channel].handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOLEAN
|
|
||||||
ChannelPlaying (COUNT WhichChannel)
|
|
||||||
{
|
|
||||||
ALint state;
|
|
||||||
|
|
||||||
alGetSourcei (soundSource[WhichChannel].handle, AL_SOURCE_STATE, &state);
|
|
||||||
if (state == AL_PLAYING)
|
|
||||||
return TRUE;
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
SetChannelVolume (COUNT channel, COUNT volume, BYTE priority)
|
|
||||||
// I wonder what this whole priority business is...
|
|
||||||
// I can probably ignore it.
|
|
||||||
{
|
|
||||||
alSourcef (soundSource[channel].handle, AL_GAIN,
|
|
||||||
(volume / (ALfloat)MAX_VOLUME) * sfxVolumeScale);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Status: Ignored
|
|
||||||
PBYTE
|
|
||||||
GetSampleAddress (SOUND sound)
|
|
||||||
// I might be prototyping this wrong, type-wise.
|
|
||||||
{
|
|
||||||
return ((PBYTE)GetSoundAddress (sound));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Status: Ignored
|
|
||||||
COUNT
|
|
||||||
GetSampleLength (SOUND sound)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Status: Ignored
|
|
||||||
void
|
|
||||||
SetChannelRate (COUNT channel, DWORD rate_hz, unsigned char priority)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// Status: Ignored
|
|
||||||
COUNT
|
|
||||||
GetSampleRate (SOUND sound)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
MEM_HANDLE
|
|
||||||
_GetSoundBankData (FILE *fp, DWORD length)
|
|
||||||
{
|
|
||||||
#ifdef WIN32
|
|
||||||
int omode;
|
|
||||||
#endif
|
|
||||||
int snd_ct, n;
|
|
||||||
DWORD opos;
|
|
||||||
char CurrentLine[1024], filename[1024];
|
|
||||||
#define MAX_FX 256
|
|
||||||
TFB_SoundSample *sndfx[MAX_FX];
|
|
||||||
STRING_TABLE Snd;
|
|
||||||
|
|
||||||
opos = ftell (fp);
|
|
||||||
|
|
||||||
{
|
|
||||||
char *s1, *s2;
|
|
||||||
extern char *_cur_resfile_name;
|
|
||||||
|
|
||||||
if (_cur_resfile_name == 0
|
|
||||||
|| (((s2 = 0), (s1 = strrchr (_cur_resfile_name, '/')) == 0)
|
|
||||||
&& (s2 = strrchr (_cur_resfile_name, '\\')) == 0))
|
|
||||||
n = 0;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (s2 > s1)
|
|
||||||
s1 = s2;
|
|
||||||
n = s1 - _cur_resfile_name + 1;
|
|
||||||
strncpy (filename, _cur_resfile_name, n);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
omode = _setmode (fileno (fp), O_TEXT);
|
|
||||||
#endif
|
|
||||||
snd_ct = 0;
|
|
||||||
while (fgets (CurrentLine, sizeof (CurrentLine), fp) && snd_ct < MAX_FX)
|
|
||||||
{
|
|
||||||
if (sscanf(CurrentLine, "%s", &filename[n]) == 1)
|
|
||||||
{
|
|
||||||
fprintf (stderr, "_GetSoundBankData(): loading %s\n", filename);
|
|
||||||
|
|
||||||
sndfx[snd_ct] = (TFB_SoundSample *) HMalloc (sizeof (TFB_SoundSample));
|
|
||||||
sndfx[snd_ct]->buffer_tag = 0;
|
|
||||||
sndfx[snd_ct]->read_chain_ptr = NULL;
|
|
||||||
sndfx[snd_ct]->decoder = SoundDecoder_Load (filename, 4096, 0, 0);
|
|
||||||
if (!sndfx[snd_ct]->decoder)
|
|
||||||
{
|
|
||||||
fprintf (stderr, "_GetSoundBankData(): couldn't load %s\n", filename);
|
|
||||||
HFree (sndfx[snd_ct]);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ALuint decoded_bytes;
|
|
||||||
|
|
||||||
decoded_bytes = SoundDecoder_DecodeAll (sndfx[snd_ct]->decoder);
|
|
||||||
//fprintf (stderr, "_GetSoundBankData(): decoded_bytes %d\n", decoded_bytes);
|
|
||||||
|
|
||||||
sndfx[snd_ct]->num_buffers = 1;
|
|
||||||
sndfx[snd_ct]->buffer = (ALuint *) HMalloc (sizeof (ALuint) * sndfx[snd_ct]->num_buffers);
|
|
||||||
alGenBuffers (sndfx[snd_ct]->num_buffers, sndfx[snd_ct]->buffer);
|
|
||||||
alBufferData (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
|
|
||||||
{
|
|
||||||
fprintf (stderr, "_GetSoundBankData: Bad file!\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
// pkunk insult fix 2002/11/12 (ftell shouldn't be needed for loop to terminate)
|
|
||||||
/*if (ftell (fp) - opos >= length)
|
|
||||||
break;*/
|
|
||||||
}
|
|
||||||
#ifdef WIN32
|
|
||||||
_setmode (fileno (fp), omode);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Snd = 0;
|
|
||||||
if (snd_ct && (Snd = AllocStringTable (
|
|
||||||
sizeof (STRING_TABLE_DESC)
|
|
||||||
+ (sizeof (DWORD) * snd_ct)
|
|
||||||
+ (sizeof (sndfx[0]) * snd_ct)
|
|
||||||
)))
|
|
||||||
{
|
|
||||||
STRING_TABLEPTR fxTab;
|
|
||||||
|
|
||||||
LockStringTable (Snd, &fxTab);
|
|
||||||
if (fxTab == 0)
|
|
||||||
{
|
|
||||||
while (snd_ct--)
|
|
||||||
{
|
|
||||||
if (sndfx[snd_ct]->decoder)
|
|
||||||
SoundDecoder_Free (sndfx[snd_ct]->decoder);
|
|
||||||
HFree (sndfx[snd_ct]);
|
|
||||||
}
|
|
||||||
|
|
||||||
FreeStringTable (Snd);
|
|
||||||
Snd = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DWORD *offs, StringOffs;
|
|
||||||
|
|
||||||
fxTab->StringCount = snd_ct;
|
|
||||||
fxTab->flags = 0;
|
|
||||||
offs = fxTab->StringOffsets;
|
|
||||||
StringOffs = sizeof (STRING_TABLE_DESC) + (sizeof (DWORD) * snd_ct);
|
|
||||||
memcpy ((BYTE *)fxTab + StringOffs, sndfx, sizeof (sndfx[0]) * snd_ct);
|
|
||||||
do
|
|
||||||
{
|
|
||||||
*offs++ = StringOffs;
|
|
||||||
StringOffs += sizeof (sndfx[0]);
|
|
||||||
} while (snd_ct--);
|
|
||||||
UnlockStringTable (Snd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ((MEM_HANDLE)Snd);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOLEAN
|
|
||||||
_ReleaseSoundBankData (MEM_HANDLE Snd)
|
|
||||||
{
|
|
||||||
STRING_TABLEPTR fxTab;
|
|
||||||
|
|
||||||
LockStringTable (Snd, &fxTab);
|
|
||||||
if (fxTab)
|
|
||||||
{
|
|
||||||
int snd_ct;
|
|
||||||
TFB_SoundSample **sptr;
|
|
||||||
|
|
||||||
snd_ct = fxTab->StringCount;
|
|
||||||
sptr = (TFB_SoundSample **)((BYTE *)fxTab + fxTab->StringOffsets[0]);
|
|
||||||
while (snd_ct--)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < NUM_SOUNDSOURCES; ++i)
|
|
||||||
{
|
|
||||||
if (soundSource[i].sample == (*sptr))
|
|
||||||
soundSource[i].sample = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((*sptr)->decoder)
|
|
||||||
SoundDecoder_Free ((*sptr)->decoder);
|
|
||||||
alDeleteBuffers ((*sptr)->num_buffers, (*sptr)->buffer);
|
|
||||||
HFree ((*sptr)->buffer);
|
|
||||||
HFree (*sptr);
|
|
||||||
*sptr++ = 0;
|
|
||||||
}
|
|
||||||
UnlockStringTable (Snd);
|
|
||||||
FreeStringTable (Snd);
|
|
||||||
|
|
||||||
return (TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOLEAN
|
|
||||||
DestroySound(SOUND_REF target)
|
|
||||||
{
|
|
||||||
return (_ReleaseSoundBankData (target));
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,112 +0,0 @@
|
|||||||
/*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* OpenAL specific code by Mika Kolehmainen, 2002-10-23
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
#include <al.h>
|
|
||||||
#include <alc.h>
|
|
||||||
#pragma comment (lib, "OpenAL32.lib")
|
|
||||||
#else
|
|
||||||
#include <AL/al.h>
|
|
||||||
#include <AL/alc.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "starcon.h"
|
|
||||||
#include "misc.h"
|
|
||||||
#include "libs/strings/strintrn.h"
|
|
||||||
#include "libs/sound/sndintrn.h"
|
|
||||||
#include "libs/sound/sound_common.h"
|
|
||||||
#include "mixer.h"
|
|
||||||
#include "libs/sound/decoders/decoder.h"
|
|
||||||
|
|
||||||
|
|
||||||
#define FIRST_SFX_SOURCE 0
|
|
||||||
#define LAST_SFX_SOURCE 4
|
|
||||||
#define MUSIC_SOURCE (LAST_SFX_SOURCE + 1)
|
|
||||||
#define SPEECH_SOURCE (MUSIC_SOURCE + 1)
|
|
||||||
#define NUM_SOUNDSOURCES (SPEECH_SOURCE + 1)
|
|
||||||
#define PAD_SCOPE_BYTES 8096
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
ALuint buf_name;
|
|
||||||
int type;
|
|
||||||
void *value;
|
|
||||||
} TFB_SoundTag;
|
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
AL_BUFFER_TAG_TEXT = 1,
|
|
||||||
AL_BUFFER_TAG_TEXTPAGE
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct tfb_soundchain
|
|
||||||
{
|
|
||||||
TFB_SoundDecoder *decoder; // points at the decoder to read from
|
|
||||||
float start_time;
|
|
||||||
TFB_SoundTag tag;
|
|
||||||
struct tfb_soundchain *next;
|
|
||||||
} TFB_SoundChain;
|
|
||||||
|
|
||||||
// audio data
|
|
||||||
typedef struct tfb_soundsample
|
|
||||||
{
|
|
||||||
TFB_SoundDecoder *decoder; // decoder to read from
|
|
||||||
TFB_SoundChain *read_chain_ptr; // points to chain read poistion
|
|
||||||
TFB_SoundChain *play_chain_ptr; // points to chain playing position
|
|
||||||
float length; // total length of decoder chain in seconds
|
|
||||||
ALuint *buffer;
|
|
||||||
ALuint num_buffers;
|
|
||||||
TFB_SoundTag **buffer_tag;
|
|
||||||
} TFB_SoundSample;
|
|
||||||
|
|
||||||
|
|
||||||
// equivalent to channel in legacy sound code
|
|
||||||
typedef struct tfb_soundsource
|
|
||||||
{
|
|
||||||
TFB_SoundSample *sample;
|
|
||||||
ALuint handle;
|
|
||||||
BOOLEAN stream_should_be_playing;
|
|
||||||
Mutex stream_mutex;
|
|
||||||
ALint start_time;
|
|
||||||
|
|
||||||
// for oscilloscope
|
|
||||||
void *sbuffer;
|
|
||||||
ALuint sbuf_start;
|
|
||||||
ALuint sbuf_size;
|
|
||||||
ALuint sbuf_offset;
|
|
||||||
ALuint sbuf_lasttime;
|
|
||||||
} TFB_SoundSource;
|
|
||||||
|
|
||||||
|
|
||||||
extern ALCcontext *alcContext; // OpenAL context
|
|
||||||
extern ALCdevice *alcDevice; // OpenAL device
|
|
||||||
extern ALfloat listenerPos[]; // listener position (3 floats)
|
|
||||||
extern ALfloat listenerVel[]; // listener velocity (3 floats)
|
|
||||||
extern ALfloat listenerOri[]; // listener orientation (two 3 float vectors, "look at" and "up")
|
|
||||||
extern TFB_SoundSource soundSource[];
|
|
||||||
|
|
||||||
void SetSFXVolume (float volume);
|
|
||||||
void SetSpeechVolume (float volume);
|
|
||||||
void DoTrackTag (TFB_SoundTag *tag);
|
|
||||||
|
|
||||||
TFB_SoundChain *create_soundchain (TFB_SoundDecoder *decoder, float startTime);
|
|
||||||
void destroy_soundchain (TFB_SoundChain *chain);
|
|
||||||
TFB_SoundChain *get_previous_chain (TFB_SoundChain *first_chain, TFB_SoundChain *current_chain);
|
|
||||||
|
|
||||||
#include "stream.h"
|
|
||||||
+2
-117
@@ -16,17 +16,15 @@
|
|||||||
|
|
||||||
/* OpenAL specific code by Mika Kolehmainen, 2002-10-23
|
/* OpenAL specific code by Mika Kolehmainen, 2002-10-23
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef SOUNDMODULE_OPENAL
|
#ifdef SOUNDMODULE_OPENAL
|
||||||
|
|
||||||
#include "sound.h"
|
#include "libs/sound/sound.h"
|
||||||
|
|
||||||
ALCcontext *alcContext = NULL;
|
ALCcontext *alcContext = NULL;
|
||||||
ALCdevice *alcDevice = NULL;
|
ALCdevice *alcDevice = NULL;
|
||||||
ALfloat listenerPos[] = {0.0f, 0.0f, 0.0f};
|
ALfloat listenerPos[] = {0.0f, 0.0f, 0.0f};
|
||||||
ALfloat listenerVel[] = {0.0f, 0.0f, 0.0f};
|
ALfloat listenerVel[] = {0.0f, 0.0f, 0.0f};
|
||||||
ALfloat listenerOri[] = {0.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f};
|
ALfloat listenerOri[] = {0.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f};
|
||||||
TFB_SoundSource soundSource[NUM_SOUNDSOURCES];
|
|
||||||
static Task StreamDecoderTask;
|
static Task StreamDecoderTask;
|
||||||
|
|
||||||
|
|
||||||
@@ -143,117 +141,4 @@ TFB_UninitSound (void)
|
|||||||
SoundDecoder_Uninit ();
|
SoundDecoder_Uninit ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
#endif
|
||||||
StopSound (void)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = FIRST_SFX_SOURCE; i <= LAST_SFX_SOURCE; ++i)
|
|
||||||
{
|
|
||||||
alSourceRewind (soundSource[i].handle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOLEAN
|
|
||||||
SoundPlaying (void)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < NUM_SOUNDSOURCES; ++i)
|
|
||||||
{
|
|
||||||
TFB_SoundSample *sample;
|
|
||||||
sample = soundSource[i].sample;
|
|
||||||
if (sample && sample->decoder)
|
|
||||||
{
|
|
||||||
BOOLEAN result;
|
|
||||||
LockMutex (soundSource[i].stream_mutex);
|
|
||||||
result = PlayingStream (i);
|
|
||||||
UnlockMutex (soundSource[i].stream_mutex);
|
|
||||||
if (result)
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ALint state;
|
|
||||||
alGetSourcei (soundSource[i].handle, AL_SOURCE_STATE, &state);
|
|
||||||
if (state == AL_PLAYING)
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
TFB_SoundChain *
|
|
||||||
create_soundchain (TFB_SoundDecoder *decoder, float startTime)
|
|
||||||
{
|
|
||||||
TFB_SoundChain *chain;
|
|
||||||
chain = (TFB_SoundChain *)HMalloc (sizeof (TFB_SoundChain));
|
|
||||||
chain->decoder = decoder;
|
|
||||||
chain->next =NULL;
|
|
||||||
chain->start_time = startTime;
|
|
||||||
chain->tag.buf_name = 0;
|
|
||||||
chain->tag.type = 0;
|
|
||||||
return (chain);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
destroy_soundchain (TFB_SoundChain *chain)
|
|
||||||
{
|
|
||||||
while (chain->next)
|
|
||||||
{
|
|
||||||
TFB_SoundChain *tmp_chain = chain->next;
|
|
||||||
chain->next = chain->next->next;
|
|
||||||
if (tmp_chain->decoder)
|
|
||||||
SoundDecoder_Free (tmp_chain->decoder);
|
|
||||||
HFree (tmp_chain);
|
|
||||||
}
|
|
||||||
SoundDecoder_Free (chain->decoder);
|
|
||||||
HFree (chain);
|
|
||||||
}
|
|
||||||
|
|
||||||
TFB_SoundChain *
|
|
||||||
get_previous_chain (TFB_SoundChain *first_chain, TFB_SoundChain *current_chain)
|
|
||||||
{
|
|
||||||
TFB_SoundChain *prev_chain;
|
|
||||||
prev_chain = first_chain;
|
|
||||||
if (prev_chain == current_chain)
|
|
||||||
return (prev_chain);
|
|
||||||
while (prev_chain->next)
|
|
||||||
{
|
|
||||||
if (prev_chain->next == current_chain)
|
|
||||||
return (prev_chain);
|
|
||||||
prev_chain = prev_chain->next;
|
|
||||||
}
|
|
||||||
return (first_chain);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Status: Ignored
|
|
||||||
BOOLEAN
|
|
||||||
InitSound (int argc, char* argv[])
|
|
||||||
{
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Status: Ignored
|
|
||||||
void
|
|
||||||
UninitSound (void)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetSFXVolume (float volume)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
for (i = FIRST_SFX_SOURCE; i <= LAST_SFX_SOURCE; ++i)
|
|
||||||
{
|
|
||||||
alSourcef (soundSource[i].handle, AL_GAIN, volume);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetSpeechVolume (float volume)
|
|
||||||
{
|
|
||||||
alSourcef (soundSource[SPEECH_SOURCE].handle, AL_GAIN, volume);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
/*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* OpenAL specific code by Mika Kolehmainen, 2002-10-23
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#include <al.h>
|
||||||
|
#include <alc.h>
|
||||||
|
#pragma comment (lib, "OpenAL32.lib")
|
||||||
|
#else
|
||||||
|
#include <AL/al.h>
|
||||||
|
#include <AL/alc.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "mixer.h"
|
||||||
|
|
||||||
|
#define TFBSound_Object ALuint
|
||||||
|
|
||||||
|
/*************************************************
|
||||||
|
* General interface
|
||||||
|
*/
|
||||||
|
#define TFBSound_GetError alGetError
|
||||||
|
#define TFBSound_OpenAudio alOpenAudio
|
||||||
|
#define TFBSound_CloseAudio alCloseAudio
|
||||||
|
#define TFBSound_QuerySpec alQuerySpec
|
||||||
|
|
||||||
|
/*************************************************
|
||||||
|
* Sources
|
||||||
|
*/
|
||||||
|
#define TFBSound_GenSources alGenSources
|
||||||
|
#define TFBSound_DeleteSources alDeleteSources
|
||||||
|
#define TFBSound_IsSource alIsSource
|
||||||
|
#define TFBSound_Sourcei alSourcei
|
||||||
|
#define TFBSound_Sourcef alSourcef
|
||||||
|
#define TFBSound_GetSourcei alGetSourcei
|
||||||
|
#define TFBSound_GetSourcef alGetSourcef
|
||||||
|
#define TFBSound_SourceRewind alSourceRewind
|
||||||
|
#define TFBSound_SourcePlay alSourcePlay
|
||||||
|
#define TFBSound_SourcePause alSourcePause
|
||||||
|
#define TFBSound_SourceStop alSourceStop
|
||||||
|
#define TFBSound_SourceQueueBuffers alSourceQueueBuffers
|
||||||
|
#define TFBSound_SourceUnqueueBuffers alSourceUnqueueBuffers
|
||||||
|
|
||||||
|
/*************************************************
|
||||||
|
* Buffers
|
||||||
|
*/
|
||||||
|
#define TFBSound_GenBuffers alGenBuffers
|
||||||
|
#define TFBSound_DeleteBuffers alDeleteBuffers
|
||||||
|
#define TFBSound_IsBuffer alIsBuffer
|
||||||
|
#define TFBSound_GetBufferi alGetBufferi
|
||||||
|
#define TFBSound_BufferData alBufferData
|
||||||
|
#define TFBSound_ConvertBuffer alConvertBuffer
|
||||||
|
#define TFBSound_BufferData_Linux alBufferWriteData_LOKI
|
||||||
|
|
||||||
|
#define TFBSOUND_GAIN AL_GAIN
|
||||||
|
#define TFBSOUND_BUFFER AL_BUFFER
|
||||||
|
#define TFBSOUND_SOURCE_STATE AL_SOURCE_STATE
|
||||||
|
#define TFBSOUND_PLAYING AL_PLAYING
|
||||||
|
#define TFBSOUND_PAUSED AL_PAUSED
|
||||||
|
#define TFBSOUND_FORMAT_MONO16 AL_FORMAT_MONO16
|
||||||
|
#define TFBSOUND_FORMAT_STEREO16 AL_FORMAT_STEREO16
|
||||||
|
#define TFBSOUND_FORMAT_STEREO8 AL_FORMAT_STEREO8
|
||||||
|
#define TFBSOUND_LOOPING AL_LOOPING
|
||||||
|
#define TFBSOUND_BUFFERS_PROCESSED AL_BUFFERS_PROCESSED
|
||||||
|
#define TFBSOUND_BUFFERS_QUEUED AL_BUFFERS_QUEUED
|
||||||
|
#define TFBSOUND_NO_ERROR AL_NO_ERROR
|
||||||
|
#define TFBSOUND_SIZE AL_SIZE
|
||||||
@@ -1,449 +0,0 @@
|
|||||||
/*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* By Mika Kolehmainen, 2002-10-23
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef SOUNDMODULE_OPENAL
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include "sound.h"
|
|
||||||
|
|
||||||
#if !defined (WIN32) // && !defined (MacOS and BeOS too)
|
|
||||||
#include <AL/alext.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
BOOLEAN speech_advancetrack = FALSE;
|
|
||||||
|
|
||||||
void
|
|
||||||
PlayStream (TFB_SoundSample *sample, ALuint source, ALboolean looping,
|
|
||||||
ALboolean scope, ALboolean rewind)
|
|
||||||
{
|
|
||||||
ALuint i, pos = 0;
|
|
||||||
ALint offset = 0;
|
|
||||||
if (!sample || (!sample->read_chain_ptr && !sample->decoder))
|
|
||||||
return;
|
|
||||||
|
|
||||||
StopStream (source);
|
|
||||||
if (sample->read_chain_ptr)
|
|
||||||
{
|
|
||||||
sample->decoder = sample->read_chain_ptr->decoder;
|
|
||||||
offset = (ALint) (sample->read_chain_ptr->start_time * (float)ONE_SECOND);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
offset= 0;
|
|
||||||
if (rewind)
|
|
||||||
SoundDecoder_Rewind (sample->decoder);
|
|
||||||
else
|
|
||||||
offset += (ALint)(SoundDecoder_GetTime (sample->decoder) * (float)ONE_SECOND);
|
|
||||||
soundSource[source].sample = sample;
|
|
||||||
soundSource[source].sample->play_chain_ptr = sample->read_chain_ptr;
|
|
||||||
soundSource[source].sample->decoder->looping = looping;
|
|
||||||
alSourcei (soundSource[source].handle, AL_LOOPING, AL_FALSE);
|
|
||||||
|
|
||||||
if (scope)
|
|
||||||
{
|
|
||||||
pos = PAD_SCOPE_BYTES;
|
|
||||||
soundSource[source].sbuffer = HMalloc (pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sample->read_chain_ptr && sample->read_chain_ptr->tag.type)
|
|
||||||
{
|
|
||||||
DoTrackTag(&sample->read_chain_ptr->tag);
|
|
||||||
}
|
|
||||||
for (i = 0; i < sample->num_buffers; ++i)
|
|
||||||
{
|
|
||||||
ALuint decoded_bytes;
|
|
||||||
if (sample->buffer_tag)
|
|
||||||
sample->buffer_tag[i] = 0;
|
|
||||||
decoded_bytes = SoundDecoder_Decode (sample->decoder);
|
|
||||||
//fprintf (stderr, "PlayStream(): source %d filename:%s start: %d position:%d bytes %d\n", source,
|
|
||||||
// sample->decoder->filename, sample->decoder->start_sample,
|
|
||||||
// sample->decoder->pos, decoded_bytes);
|
|
||||||
if (decoded_bytes == 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
#if !defined (WIN32) // && !defined (MacOS and BeOS too)
|
|
||||||
// *nix OpenAL implementation has to handle stereo data differently to avoid mixing it to mono
|
|
||||||
|
|
||||||
if (sample->decoder->format == AL_FORMAT_STEREO8 ||
|
|
||||||
sample->decoder->format == AL_FORMAT_STEREO16)
|
|
||||||
{
|
|
||||||
alBufferWriteData_LOKI (sample->buffer[i], sample->decoder->format, sample->decoder->buffer,
|
|
||||||
decoded_bytes, sample->decoder->frequency, sample->decoder->format);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
alBufferData (sample->buffer[i], sample->decoder->format, sample->decoder->buffer,
|
|
||||||
decoded_bytes, sample->decoder->frequency);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
alBufferData (sample->buffer[i], sample->decoder->format, sample->decoder->buffer,
|
|
||||||
decoded_bytes, sample->decoder->frequency);
|
|
||||||
#endif
|
|
||||||
alSourceQueueBuffers (soundSource[source].handle, 1, &sample->buffer[i]);
|
|
||||||
|
|
||||||
if (scope)
|
|
||||||
{
|
|
||||||
UBYTE *p;
|
|
||||||
soundSource[source].sbuffer = HRealloc (soundSource[source].sbuffer,
|
|
||||||
pos + decoded_bytes);
|
|
||||||
p = (UBYTE *)soundSource[source].sbuffer;
|
|
||||||
memcpy (&p[pos], sample->decoder->buffer, decoded_bytes);
|
|
||||||
pos += decoded_bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sample->decoder->error)
|
|
||||||
{
|
|
||||||
if (sample->decoder->error == SOUNDDECODER_EOF && sample->read_chain_ptr->next)
|
|
||||||
{
|
|
||||||
sample->read_chain_ptr = sample->read_chain_ptr->next;
|
|
||||||
sample->decoder = sample->read_chain_ptr->decoder;
|
|
||||||
SoundDecoder_Rewind (sample->decoder);
|
|
||||||
fprintf (stderr, "Switching to stream %s at pos %d\n",
|
|
||||||
sample->decoder->filename, sample->decoder->start_sample);
|
|
||||||
if (sample->buffer_tag && sample->read_chain_ptr->tag.type)
|
|
||||||
{
|
|
||||||
sample->buffer_tag[i] = &sample->read_chain_ptr->tag;
|
|
||||||
sample->read_chain_ptr->tag.buf_name = sample->buffer[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (sample->buffer_tag)
|
|
||||||
for ( ; i <sample->num_buffers; ++i)
|
|
||||||
sample->buffer_tag[i] = 0;
|
|
||||||
soundSource[source].sbuf_size = pos;
|
|
||||||
soundSource[source].sbuf_start = pos - PAD_SCOPE_BYTES;
|
|
||||||
soundSource[source].sbuf_lasttime = GetTimeCounter ();
|
|
||||||
soundSource[source].start_time = (ALint)GetTimeCounter () - offset;
|
|
||||||
soundSource[source].stream_should_be_playing = TRUE;
|
|
||||||
alSourcePlay (soundSource[source].handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
StopStream (ALuint source)
|
|
||||||
{
|
|
||||||
ALuint queued, processed;
|
|
||||||
ALuint *buffer;
|
|
||||||
|
|
||||||
soundSource[source].stream_should_be_playing = FALSE;
|
|
||||||
soundSource[source].sample = NULL;
|
|
||||||
|
|
||||||
if (soundSource[source].sbuffer)
|
|
||||||
{
|
|
||||||
void *sbuffer = soundSource[source].sbuffer;
|
|
||||||
soundSource[source].sbuffer = NULL;
|
|
||||||
HFree (sbuffer);
|
|
||||||
}
|
|
||||||
soundSource[source].sbuf_start = 0;
|
|
||||||
soundSource[source].sbuf_size = 0;
|
|
||||||
soundSource[source].sbuf_offset = 0;
|
|
||||||
|
|
||||||
alSourceStop (soundSource[source].handle);
|
|
||||||
alGetSourcei (soundSource[source].handle, AL_BUFFERS_PROCESSED, &processed);
|
|
||||||
alGetSourcei (soundSource[source].handle, AL_BUFFERS_QUEUED, &queued);
|
|
||||||
|
|
||||||
//fprintf (stderr, "StopStream(): source %d processed %d queued %d num_buffers %d\n", source, processed, queued, soundSource[source].sample->num_buffers);
|
|
||||||
|
|
||||||
if (processed != 0)
|
|
||||||
{
|
|
||||||
buffer = (ALuint *) HMalloc (sizeof (ALuint) * processed);
|
|
||||||
alSourceUnqueueBuffers (soundSource[source].handle, processed, buffer);
|
|
||||||
HFree (buffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PauseStream (ALuint source)
|
|
||||||
{
|
|
||||||
// TODO: how to handle start_time
|
|
||||||
soundSource[source].stream_should_be_playing = FALSE;
|
|
||||||
alSourcePause (soundSource[source].handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
ResumeStream (ALuint source)
|
|
||||||
{
|
|
||||||
// TODO: how to handle start_time
|
|
||||||
soundSource[source].stream_should_be_playing = TRUE;
|
|
||||||
alSourcePlay (soundSource[source].handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOLEAN
|
|
||||||
PlayingStream (ALuint source)
|
|
||||||
{
|
|
||||||
return soundSource[source].stream_should_be_playing;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
StreamDecoderTaskFunc (void *data)
|
|
||||||
{
|
|
||||||
Task task = (Task)data;
|
|
||||||
int i;
|
|
||||||
ALuint last_buffer[NUM_SOUNDSOURCES];
|
|
||||||
|
|
||||||
for (i = 0; i < NUM_SOUNDSOURCES; i++)
|
|
||||||
last_buffer[i] = 0;
|
|
||||||
|
|
||||||
while (!Task_ReadState (task, TASK_EXIT))
|
|
||||||
{
|
|
||||||
|
|
||||||
TaskSwitch ();
|
|
||||||
|
|
||||||
for (i = MUSIC_SOURCE; i < NUM_SOUNDSOURCES; ++i)
|
|
||||||
{
|
|
||||||
ALuint processed, queued;
|
|
||||||
ALint state;
|
|
||||||
ALboolean do_speech_advancetrack = AL_FALSE;
|
|
||||||
|
|
||||||
LockMutex (soundSource[i].stream_mutex);
|
|
||||||
|
|
||||||
if (!soundSource[i].sample ||
|
|
||||||
!soundSource[i].sample->decoder ||
|
|
||||||
!soundSource[i].stream_should_be_playing ||
|
|
||||||
soundSource[i].sample->decoder->error == SOUNDDECODER_ERROR)
|
|
||||||
{
|
|
||||||
UnlockMutex (soundSource[i].stream_mutex);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
alGetSourcei (soundSource[i].handle, AL_BUFFERS_PROCESSED, &processed);
|
|
||||||
alGetSourcei (soundSource[i].handle, AL_BUFFERS_QUEUED, &queued);
|
|
||||||
|
|
||||||
if (processed == 0)
|
|
||||||
{
|
|
||||||
alGetSourcei (soundSource[i].handle, AL_SOURCE_STATE, &state);
|
|
||||||
if (state != AL_PLAYING)
|
|
||||||
{
|
|
||||||
if (queued == 0 && soundSource[i].sample->decoder->error == SOUNDDECODER_EOF)
|
|
||||||
{
|
|
||||||
fprintf (stderr, "StreamDecoderTaskFunc(): finished playing %s, source %d\n", soundSource[i].sample->decoder->filename, i);
|
|
||||||
soundSource[i].stream_should_be_playing = FALSE;
|
|
||||||
if (i == SPEECH_SOURCE)
|
|
||||||
{
|
|
||||||
soundSource[i].sample->decoder = NULL;
|
|
||||||
soundSource[i].sample->read_chain_ptr = NULL;
|
|
||||||
if (speech_advancetrack)
|
|
||||||
do_speech_advancetrack = AL_TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fprintf (stderr, "StreamDecoderTaskFunc(): buffer underrun when playing %s, source %d\n",
|
|
||||||
soundSource[i].sample->decoder->filename, i);
|
|
||||||
alSourcePlay (soundSource[i].handle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//fprintf (stderr, "StreamDecoderTaskFunc(): source %d, processed %d queued %d\n", i, processed, queued);
|
|
||||||
|
|
||||||
while (processed)
|
|
||||||
{
|
|
||||||
ALenum error;
|
|
||||||
ALuint buffer;
|
|
||||||
ALuint decoded_bytes;
|
|
||||||
ALuint buf_num;
|
|
||||||
|
|
||||||
alGetError (); // clear error state
|
|
||||||
|
|
||||||
alSourceUnqueueBuffers (soundSource[i].handle, 1, &buffer);
|
|
||||||
|
|
||||||
if ((error = alGetError()) != AL_NO_ERROR)
|
|
||||||
{
|
|
||||||
fprintf (stderr, "StreamDecoderTaskFunc(): OpenAL error after alSourceUnqueueBuffers: %x, file %s, source %d\n", error, soundSource[i].sample->decoder->filename, i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i == SPEECH_SOURCE)
|
|
||||||
{
|
|
||||||
for (buf_num = 0; buf_num < soundSource[i].sample->num_buffers; buf_num++)
|
|
||||||
{
|
|
||||||
TFB_SoundTag *cur_tag = soundSource[i].sample->buffer_tag[buf_num];
|
|
||||||
if (cur_tag && cur_tag->buf_name == buffer)
|
|
||||||
{
|
|
||||||
// ...do tag stuff ...
|
|
||||||
DoTrackTag (cur_tag);
|
|
||||||
soundSource[i].sample->buffer_tag[buf_num] = NULL;
|
|
||||||
soundSource[i].sample->play_chain_ptr = soundSource[i].sample->read_chain_ptr;
|
|
||||||
cur_tag->buf_name = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
ALuint buf_size;
|
|
||||||
soundSource[i].sbuf_lasttime = GetTimeCounter ();
|
|
||||||
alGetBufferi(buffer, AL_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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (soundSource[i].sample->decoder->error)
|
|
||||||
{
|
|
||||||
if (soundSource[i].sample->decoder->error == SOUNDDECODER_EOF)
|
|
||||||
{
|
|
||||||
if (soundSource[i].sample->read_chain_ptr &&
|
|
||||||
soundSource[i].sample->read_chain_ptr->next)
|
|
||||||
{
|
|
||||||
soundSource[i].sample->read_chain_ptr = soundSource[i].sample->read_chain_ptr->next;
|
|
||||||
soundSource[i].sample->decoder = soundSource[i].sample->read_chain_ptr->decoder;
|
|
||||||
SoundDecoder_Rewind (soundSource[i].sample->decoder);
|
|
||||||
fprintf (stderr, "Switching to stream %s at pos %d\n",
|
|
||||||
soundSource[i].sample->decoder->filename,
|
|
||||||
soundSource[i].sample->decoder->start_sample);
|
|
||||||
if (i == SPEECH_SOURCE)
|
|
||||||
{
|
|
||||||
for (buf_num = 0; buf_num < soundSource[i].sample->num_buffers; buf_num++)
|
|
||||||
{
|
|
||||||
if (soundSource[i].sample->buffer_tag[buf_num] == 0)
|
|
||||||
{
|
|
||||||
soundSource[i].sample->buffer_tag[buf_num] = &soundSource[i].sample->read_chain_ptr->tag;
|
|
||||||
soundSource[i].sample->read_chain_ptr->tag.buf_name = last_buffer[i];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//fprintf (stderr, "StreamDecoderTaskFunc(): decoder->error is eof for %s\n", soundSource[i].sample->decoder->filename);
|
|
||||||
processed--;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//fprintf (stderr, "StreamDecoderTaskFunc(): decoder->error is %d for %s\n", soundSource[i].sample->decoder->error, soundSource[i].sample->decoder->filename);
|
|
||||||
processed--;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
decoded_bytes = SoundDecoder_Decode (soundSource[i].sample->decoder);
|
|
||||||
if (soundSource[i].sample->decoder->error == SOUNDDECODER_ERROR)
|
|
||||||
{
|
|
||||||
fprintf (stderr, "StreamDecoderTaskFunc(): SoundDecoder_Decode error %d, file %s, source %d\n", soundSource[i].sample->decoder->error, soundSource[i].sample->decoder->filename, i);
|
|
||||||
soundSource[i].stream_should_be_playing = FALSE;
|
|
||||||
processed--;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (decoded_bytes > 0)
|
|
||||||
{
|
|
||||||
#if !defined (WIN32) // && !defined (MacOS and BeOS too)
|
|
||||||
// *nix OpenAL implementation has to handle stereo data differently to avoid mixing it to mono
|
|
||||||
|
|
||||||
if (soundSource[i].sample->decoder->format == AL_FORMAT_STEREO8 ||
|
|
||||||
soundSource[i].sample->decoder->format == AL_FORMAT_STEREO16)
|
|
||||||
{
|
|
||||||
alBufferWriteData_LOKI (buffer, soundSource[i].sample->decoder->format, soundSource[i].sample->decoder->buffer,
|
|
||||||
decoded_bytes, soundSource[i].sample->decoder->frequency,
|
|
||||||
soundSource[i].sample->decoder->format);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
alBufferData (buffer, soundSource[i].sample->decoder->format,
|
|
||||||
soundSource[i].sample->decoder->buffer, decoded_bytes,
|
|
||||||
soundSource[i].sample->decoder->frequency);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
alBufferData (buffer, soundSource[i].sample->decoder->format,
|
|
||||||
soundSource[i].sample->decoder->buffer, decoded_bytes,
|
|
||||||
soundSource[i].sample->decoder->frequency);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if ((error = alGetError()) != AL_NO_ERROR)
|
|
||||||
{
|
|
||||||
fprintf (stderr, "StreamDecoderTaskFunc(): OpenAL error after alBufferData: %x, file %s, source %d, decoded_bytes %d\n",
|
|
||||||
error, soundSource[i].sample->decoder->filename, i, decoded_bytes);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
alSourceQueueBuffers (soundSource[i].handle, 1, &buffer);
|
|
||||||
last_buffer[i] = buffer;
|
|
||||||
|
|
||||||
if (soundSource[i].sbuffer)
|
|
||||||
{
|
|
||||||
// copies decoded data to oscilloscope buffer
|
|
||||||
|
|
||||||
ALuint 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)
|
|
||||||
{
|
|
||||||
//fprintf (stderr, "copying_a to %d - %d, %d bytes\n", soundSource[i].sbuf_start, j, j - soundSource[i].sbuf_start);
|
|
||||||
memcpy (&sbuffer[soundSource[i].sbuf_start], decoder_buffer, j - soundSource[i].sbuf_start);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (remaining_bytes)
|
|
||||||
{
|
|
||||||
//fprintf (stderr, "copying_b to 0 - %d\n", 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((error = alGetError()) != AL_NO_ERROR)
|
|
||||||
{
|
|
||||||
fprintf (stderr, "StreamDecoderTaskFunc(): OpenAL error after alSourceQueueBuffers: %x, file %s, source %d, decoded_bytes %d\n",
|
|
||||||
error, i, soundSource[i].sample->decoder->filename, decoded_bytes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
processed--;
|
|
||||||
}
|
|
||||||
|
|
||||||
UnlockMutex (soundSource[i].stream_mutex);
|
|
||||||
|
|
||||||
if (i == SPEECH_SOURCE)
|
|
||||||
{
|
|
||||||
if (do_speech_advancetrack)
|
|
||||||
{
|
|
||||||
fprintf (stderr, "StreamDecoderTaskFunc(): calling advance_track\n");
|
|
||||||
do_speech_advancetrack = AL_FALSE;
|
|
||||||
advance_track (0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
FinishTask (task);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
/*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* By Mika Kolehmainen, 2002-10-23
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef STREAM_H
|
|
||||||
#define STREAM_H
|
|
||||||
|
|
||||||
void PlayStream (TFB_SoundSample *sample, ALuint source, ALboolean looping,
|
|
||||||
ALboolean scope, ALboolean rewind);
|
|
||||||
void StopStream (ALuint source);
|
|
||||||
void PauseStream (ALuint source);
|
|
||||||
void ResumeStream (ALuint source);
|
|
||||||
BOOLEAN PlayingStream (ALuint source);
|
|
||||||
int StreamDecoderTaskFunc (void *data);
|
|
||||||
|
|
||||||
extern BOOLEAN speech_advancetrack;
|
|
||||||
void advance_track (int channel_finished);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,703 +0,0 @@
|
|||||||
/*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* OpenAL specific code by Mika Kolehmainen, 2002-10-23
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef SOUNDMODULE_OPENAL
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include "sound.h"
|
|
||||||
#include "libs/sound/trackplayer.h"
|
|
||||||
|
|
||||||
extern int do_subtitles (UNICODE *pStr, UNICODE *TimeStamp, int method);
|
|
||||||
|
|
||||||
static int tct; //total number of subtitle tracks
|
|
||||||
static int tcur; //currently playing subtitle track
|
|
||||||
static int cur_page = 0; //current page of subtitle track
|
|
||||||
static int no_page_break = 0;
|
|
||||||
static int no_voice;
|
|
||||||
static int track_pos_changed = 0; // set whenever ff, frev is enabled
|
|
||||||
|
|
||||||
|
|
||||||
#define MAX_CLIPS 50
|
|
||||||
|
|
||||||
static TFB_SoundSample *sound_sample = NULL;
|
|
||||||
static TFB_SoundChain *first_chain = NULL; //first decoder in linked list
|
|
||||||
static TFB_SoundChain *last_chain = NULL; //last decoder in linked list
|
|
||||||
static UNICODE *TrackTextArray[MAX_CLIPS]; //storage for subtitlle text
|
|
||||||
static Mutex track_mutex; //protects tcur and tct
|
|
||||||
|
|
||||||
void
|
|
||||||
JumpTrack (int abort)
|
|
||||||
{
|
|
||||||
speech_advancetrack = FALSE;
|
|
||||||
|
|
||||||
if (sound_sample)
|
|
||||||
{
|
|
||||||
LockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
|
||||||
StopStream (SPEECH_SOURCE);
|
|
||||||
if (abort)
|
|
||||||
{
|
|
||||||
sound_sample->read_chain_ptr = NULL;
|
|
||||||
sound_sample->decoder = NULL;
|
|
||||||
}
|
|
||||||
UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
no_voice = 1;
|
|
||||||
do_subtitles ((void *)~0, (void *)~0, 1);
|
|
||||||
|
|
||||||
if (abort)
|
|
||||||
LockMutex (track_mutex);
|
|
||||||
tcur = tct;
|
|
||||||
UnlockMutex(track_mutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
advance_track (int channel_finished)
|
|
||||||
{
|
|
||||||
if (channel_finished <= 0)
|
|
||||||
{
|
|
||||||
if (sound_sample->read_chain_ptr || sound_sample->decoder)
|
|
||||||
{
|
|
||||||
LockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
|
||||||
PlayStream (sound_sample,
|
|
||||||
SPEECH_SOURCE, AL_FALSE,
|
|
||||||
speechVolumeScale != 0.0f,
|
|
||||||
!track_pos_changed);
|
|
||||||
track_pos_changed = 0;
|
|
||||||
UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
|
||||||
}
|
|
||||||
else if (channel_finished == 0)
|
|
||||||
{
|
|
||||||
no_voice = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
ResumeTrack ()
|
|
||||||
{
|
|
||||||
if (sound_sample && sound_sample->read_chain_ptr)
|
|
||||||
{
|
|
||||||
ALint state;
|
|
||||||
|
|
||||||
LockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
|
||||||
alGetSourcei (soundSource[SPEECH_SOURCE].handle, AL_SOURCE_STATE, &state);
|
|
||||||
|
|
||||||
if (!track_pos_changed && !soundSource[SPEECH_SOURCE].stream_should_be_playing &&
|
|
||||||
state == AL_PAUSED)
|
|
||||||
{
|
|
||||||
ResumeStream (SPEECH_SOURCE);
|
|
||||||
UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
|
||||||
}
|
|
||||||
else if (!no_voice)
|
|
||||||
{
|
|
||||||
if (tcur == 0)
|
|
||||||
{
|
|
||||||
speech_advancetrack = TRUE;
|
|
||||||
}
|
|
||||||
UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
|
||||||
advance_track (-1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
COUNT
|
|
||||||
PlayingTrack ()
|
|
||||||
{
|
|
||||||
if (sound_sample->decoder)
|
|
||||||
{
|
|
||||||
int last_track, last_page;
|
|
||||||
LockMutex (track_mutex);
|
|
||||||
last_track = tcur;
|
|
||||||
last_page = cur_page;
|
|
||||||
UnlockMutex (track_mutex);
|
|
||||||
if (do_subtitles (TrackTextArray[last_track], (void *)last_page, 1) ||
|
|
||||||
(no_voice && ++tcur < tct && do_subtitles (0, (void *)~0, 1)))
|
|
||||||
{
|
|
||||||
return (tcur + 1);
|
|
||||||
}
|
|
||||||
else if (sound_sample)
|
|
||||||
{
|
|
||||||
COUNT result;
|
|
||||||
|
|
||||||
LockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
|
||||||
result = (PlayingStream (SPEECH_SOURCE) ? (COUNT)(last_track + 1) : 0);
|
|
||||||
UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
StopTrack ()
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
speech_advancetrack = FALSE;
|
|
||||||
LockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
|
||||||
StopStream (SPEECH_SOURCE);
|
|
||||||
UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
|
||||||
|
|
||||||
for (i = 0; i < tct; i++)
|
|
||||||
{
|
|
||||||
HFree (TrackTextArray[i]);
|
|
||||||
TrackTextArray[i] = 0;
|
|
||||||
}
|
|
||||||
if (first_chain)
|
|
||||||
{
|
|
||||||
destroy_soundchain (first_chain);
|
|
||||||
first_chain = NULL;
|
|
||||||
}
|
|
||||||
if (sound_sample)
|
|
||||||
{
|
|
||||||
DestroyMutex (track_mutex);
|
|
||||||
alDeleteBuffers (sound_sample->num_buffers, sound_sample->buffer);
|
|
||||||
HFree (sound_sample->buffer);
|
|
||||||
HFree (sound_sample->buffer_tag);
|
|
||||||
HFree (sound_sample);
|
|
||||||
sound_sample = NULL;
|
|
||||||
}
|
|
||||||
tct = tcur = 0;
|
|
||||||
no_voice = 0;
|
|
||||||
do_subtitles (0, (void *)~0, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
DoTrackTag (TFB_SoundTag *tag)
|
|
||||||
{
|
|
||||||
if (tag->type == AL_BUFFER_TAG_TEXT)
|
|
||||||
{
|
|
||||||
LockMutex (track_mutex);
|
|
||||||
tcur = ((int)tag->value) >> 8;
|
|
||||||
cur_page = ((int)tag->value) & 0xFF;
|
|
||||||
UnlockMutex (track_mutex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
GetTimeStamps(UNICODE *TimeStamps, unsigned long *time_stamps)
|
|
||||||
{
|
|
||||||
int pos;
|
|
||||||
int num = 0;
|
|
||||||
while (*TimeStamps && (pos = wstrcspn (TimeStamps, ",\n")))
|
|
||||||
{
|
|
||||||
UNICODE valStr[10];
|
|
||||||
wstrncpy (valStr, TimeStamps, pos);
|
|
||||||
valStr[pos] = '\0';
|
|
||||||
*time_stamps = wstrtoul(valStr,NULL,10);
|
|
||||||
if (*time_stamps)
|
|
||||||
{
|
|
||||||
num++;
|
|
||||||
time_stamps++;
|
|
||||||
}
|
|
||||||
TimeStamps += pos;
|
|
||||||
if (*TimeStamps)
|
|
||||||
TimeStamps++;
|
|
||||||
}
|
|
||||||
*time_stamps = 0;
|
|
||||||
return (num);
|
|
||||||
}
|
|
||||||
|
|
||||||
// decodes several tracks into one and adds it to queue
|
|
||||||
// track list is NULL-terminated
|
|
||||||
void
|
|
||||||
SpliceMultiTrack (UNICODE *TrackNames[], UNICODE *TrackText)
|
|
||||||
{
|
|
||||||
#define MAX_MULTI_TRACKS 20
|
|
||||||
#define MAX_MULTI_BUFFERS 100
|
|
||||||
TFB_SoundDecoder* track_decs[MAX_MULTI_TRACKS + 1];
|
|
||||||
TFB_SoundChain *begin_chain;
|
|
||||||
int tracks;
|
|
||||||
int slen;
|
|
||||||
|
|
||||||
if (!TrackText)
|
|
||||||
{
|
|
||||||
#ifdef DEBUG
|
|
||||||
fprintf (stderr, "SpliceMultiTrack(): no track text\n");
|
|
||||||
#endif
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tct >= MAX_CLIPS)
|
|
||||||
{
|
|
||||||
fprintf (stderr, "SpliceMultiTrack(): no more clip slots (%d)\n",
|
|
||||||
MAX_CLIPS);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (! sound_sample)
|
|
||||||
{
|
|
||||||
fprintf (stderr, "SpliceMultiTrack(): Cannot be called before SpliceTrack()\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf (stderr, "SpliceMultiTrack(): loading...\n");
|
|
||||||
for (tracks = 0; *TrackNames && tracks < MAX_MULTI_TRACKS; TrackNames++, tracks++)
|
|
||||||
{
|
|
||||||
track_decs[tracks] = SoundDecoder_Load (*TrackNames, 32768, 0, 0);
|
|
||||||
if (track_decs[tracks])
|
|
||||||
{
|
|
||||||
fprintf (stderr, " track: %s, decoder: %s, rate %d format %x\n",
|
|
||||||
*TrackNames,
|
|
||||||
track_decs[tracks]->decoder_info,
|
|
||||||
track_decs[tracks]->frequency,
|
|
||||||
track_decs[tracks]->format);
|
|
||||||
SoundDecoder_DecodeAll (track_decs[tracks]);
|
|
||||||
|
|
||||||
last_chain->next = create_soundchain (track_decs[tracks], sound_sample->length);
|
|
||||||
last_chain = last_chain->next;
|
|
||||||
if (tracks == 0)
|
|
||||||
begin_chain = last_chain;
|
|
||||||
sound_sample->length += track_decs[tracks]->length;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fprintf (stderr, " couldn't load %s\n", *TrackNames);
|
|
||||||
tracks--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
track_decs[tracks] = 0; // term
|
|
||||||
|
|
||||||
if (tracks == 0)
|
|
||||||
{
|
|
||||||
fprintf (stderr, " no tracks loaded\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
slen = wstrlen (TrackText);
|
|
||||||
if (tct)
|
|
||||||
{
|
|
||||||
int slen1;
|
|
||||||
slen1 = wstrlen (TrackTextArray[tct - 1]);
|
|
||||||
TrackTextArray[tct - 1] = HRealloc (TrackTextArray[tct - 1], slen1 + slen + 1);
|
|
||||||
wstrcpy (&TrackTextArray[tct - 1][slen1], TrackText);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
TrackTextArray[tct] = HMalloc (slen + 1);
|
|
||||||
wstrcpy (TrackTextArray[tct++], TrackText);
|
|
||||||
begin_chain->tag.type = AL_BUFFER_TAG_TEXT;
|
|
||||||
begin_chain->tag.value = (void *)((tct - 1) << 8);
|
|
||||||
}
|
|
||||||
no_page_break = 1;
|
|
||||||
|
|
||||||
if (tracks > 0)
|
|
||||||
return;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fprintf (stderr, " no tracks loaded\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
SpliceTrack (UNICODE *TrackName, UNICODE *TrackText, UNICODE *TimeStamp)
|
|
||||||
{
|
|
||||||
unsigned long startTime;
|
|
||||||
if (TrackText)
|
|
||||||
{
|
|
||||||
if (TrackName == 0)
|
|
||||||
{
|
|
||||||
if (tct)
|
|
||||||
{
|
|
||||||
int slen1, slen2;
|
|
||||||
UNICODE *oTT;
|
|
||||||
|
|
||||||
oTT = TrackTextArray[tct - 1];
|
|
||||||
slen1 = wstrlen (oTT);
|
|
||||||
slen2 = wstrlen (TrackText);
|
|
||||||
TrackTextArray[tct - 1] = HRealloc (oTT, slen1 + slen2 + 1);
|
|
||||||
wstrcpy (&TrackTextArray[tct - 1][slen1], TrackText);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int num_pages, cur_page;
|
|
||||||
unsigned long time_stamps[50];
|
|
||||||
|
|
||||||
if (no_page_break && tct)
|
|
||||||
{
|
|
||||||
int slen1, slen2;
|
|
||||||
UNICODE *oTT;
|
|
||||||
|
|
||||||
oTT = TrackTextArray[tct - 1];
|
|
||||||
slen1 = wstrlen (oTT);
|
|
||||||
slen2 = wstrlen (TrackText);
|
|
||||||
TrackTextArray[tct - 1] = HRealloc (oTT, slen1 + slen2 + 1);
|
|
||||||
wstrcpy (&TrackTextArray[tct - 1][slen1], TrackText);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
TrackTextArray[tct] = HMalloc (sizeof (UNICODE) * (wstrlen (TrackText) + 1));
|
|
||||||
wstrcpy (TrackTextArray[tct++], TrackText);
|
|
||||||
}
|
|
||||||
if (TimeStamp)
|
|
||||||
num_pages = GetTimeStamps (TimeStamp, time_stamps);
|
|
||||||
else
|
|
||||||
num_pages = 0;
|
|
||||||
|
|
||||||
fprintf (stderr, "SpliceTrack(): loading %s\n", TrackName);
|
|
||||||
|
|
||||||
startTime = 0;
|
|
||||||
for (cur_page = 0; cur_page <= num_pages; cur_page++)
|
|
||||||
{
|
|
||||||
if (! sound_sample)
|
|
||||||
{
|
|
||||||
TFB_SoundDecoder *decoder;
|
|
||||||
track_mutex = CreateMutex();
|
|
||||||
sound_sample = (TFB_SoundSample *) HMalloc (sizeof (TFB_SoundSample));
|
|
||||||
sound_sample->num_buffers = 8;
|
|
||||||
sound_sample->buffer_tag = HMalloc (sizeof (TFB_SoundTag *) * sound_sample->num_buffers);
|
|
||||||
sound_sample->buffer = HMalloc (sizeof (ALuint) * sound_sample->num_buffers);
|
|
||||||
alGenBuffers (sound_sample->num_buffers, sound_sample->buffer);
|
|
||||||
decoder = SoundDecoder_Load (TrackName, 4096, startTime, time_stamps[cur_page]);
|
|
||||||
sound_sample->read_chain_ptr = create_soundchain (decoder, 0.0);
|
|
||||||
sound_sample->decoder = decoder;
|
|
||||||
first_chain = last_chain = sound_sample->read_chain_ptr;
|
|
||||||
sound_sample->length = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
TFB_SoundDecoder *decoder;
|
|
||||||
decoder = SoundDecoder_Load (TrackName, 4096, startTime, time_stamps[cur_page]);
|
|
||||||
last_chain->next = create_soundchain (decoder, sound_sample->length);
|
|
||||||
last_chain = last_chain->next;
|
|
||||||
}
|
|
||||||
startTime += time_stamps[cur_page];
|
|
||||||
|
|
||||||
// fprintf (stderr, "page (%d of %d): %d\n",cur_page, num_pages, startTime);
|
|
||||||
if (last_chain->decoder)
|
|
||||||
{
|
|
||||||
//fprintf (stderr, " decoder: %s, rate %d format %x\n",
|
|
||||||
// last_chain->decoder->decoder_info,
|
|
||||||
// last_chain->decoder->frequency,
|
|
||||||
// last_chain->decoder->format);
|
|
||||||
|
|
||||||
sound_sample->length += last_chain->decoder->length;
|
|
||||||
if (! no_page_break)
|
|
||||||
{
|
|
||||||
last_chain->tag.type = AL_BUFFER_TAG_TEXT;
|
|
||||||
last_chain->tag.value = (void *)(((tct - 1) << 8) | cur_page);
|
|
||||||
}
|
|
||||||
no_page_break = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fprintf (stderr, "SpliceTrack(): couldn't load %s\n", TrackName);
|
|
||||||
alDeleteBuffers (sound_sample->num_buffers, sound_sample->buffer);
|
|
||||||
destroy_soundchain (first_chain);
|
|
||||||
first_chain = NULL;
|
|
||||||
HFree (sound_sample->buffer);
|
|
||||||
HFree (sound_sample);
|
|
||||||
sound_sample = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
PauseTrack ()
|
|
||||||
{
|
|
||||||
if (sound_sample && sound_sample->decoder)
|
|
||||||
{
|
|
||||||
LockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
|
||||||
PauseStream (SPEECH_SOURCE);
|
|
||||||
UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
recompute_track_pos (TFB_SoundSample *sample, TFB_SoundChain *first_chain, ALint offset)
|
|
||||||
{
|
|
||||||
TFB_SoundChain *cur_chain = first_chain;
|
|
||||||
while (cur_chain->next &&
|
|
||||||
(ALint)(cur_chain->next->start_time * (float)ONE_SECOND) < offset)
|
|
||||||
cur_chain = cur_chain->next;
|
|
||||||
if (cur_chain->tag.type)
|
|
||||||
DoTrackTag (&cur_chain->tag);
|
|
||||||
if ((ALint)((cur_chain->start_time + cur_chain->decoder->length) * (float)ONE_SECOND) < offset)
|
|
||||||
{
|
|
||||||
sample->read_chain_ptr = NULL;
|
|
||||||
sample->decoder = NULL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sample->read_chain_ptr = cur_chain;
|
|
||||||
SoundDecoder_Seek(sample->read_chain_ptr->decoder,
|
|
||||||
(ALuint)(1000 * (offset / (float)ONE_SECOND - cur_chain->start_time)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
FastReverse_Smooth ()
|
|
||||||
{
|
|
||||||
if (sound_sample)
|
|
||||||
{
|
|
||||||
ALint offset;
|
|
||||||
LockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
|
||||||
PauseStream (SPEECH_SOURCE);
|
|
||||||
track_pos_changed = 1;
|
|
||||||
soundSource[SPEECH_SOURCE].start_time += ACCEL_SCROLL_SPEED;
|
|
||||||
if (soundSource[SPEECH_SOURCE].start_time > (ALint)GetTimeCounter())
|
|
||||||
{
|
|
||||||
soundSource[SPEECH_SOURCE].start_time = GetTimeCounter();
|
|
||||||
offset = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
offset = GetTimeCounter() - soundSource[SPEECH_SOURCE].start_time;
|
|
||||||
recompute_track_pos(soundSource[SPEECH_SOURCE].sample, first_chain, offset);
|
|
||||||
UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
|
||||||
PlayingTrack();
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
FastReverse_Page ()
|
|
||||||
{
|
|
||||||
if (sound_sample)
|
|
||||||
{
|
|
||||||
TFB_SoundChain *prev_chain;
|
|
||||||
LockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
|
||||||
prev_chain = get_previous_chain(first_chain, sound_sample->play_chain_ptr);
|
|
||||||
if (prev_chain)
|
|
||||||
{
|
|
||||||
sound_sample->read_chain_ptr = prev_chain;
|
|
||||||
PlayStream (sound_sample,
|
|
||||||
SPEECH_SOURCE, AL_FALSE,
|
|
||||||
speechVolumeScale != 0.0f, AL_TRUE);
|
|
||||||
}
|
|
||||||
UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
FastForward_Smooth ()
|
|
||||||
{
|
|
||||||
if (sound_sample)
|
|
||||||
{
|
|
||||||
ALint offset;
|
|
||||||
LockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
|
||||||
PauseStream (SPEECH_SOURCE);
|
|
||||||
soundSource[SPEECH_SOURCE].start_time -= ACCEL_SCROLL_SPEED;
|
|
||||||
offset = GetTimeCounter() - soundSource[SPEECH_SOURCE].start_time;
|
|
||||||
track_pos_changed = 1;
|
|
||||||
recompute_track_pos(sound_sample, first_chain, offset);
|
|
||||||
UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
|
||||||
PlayingTrack();
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
FastForward_Page ()
|
|
||||||
{
|
|
||||||
if (sound_sample)
|
|
||||||
{
|
|
||||||
TFB_SoundChain *cur_ptr = sound_sample->play_chain_ptr;
|
|
||||||
LockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
|
||||||
while (cur_ptr->next && ! cur_ptr->tag.type)
|
|
||||||
cur_ptr = cur_ptr->next;
|
|
||||||
if (cur_ptr->next)
|
|
||||||
{
|
|
||||||
sound_sample->read_chain_ptr = cur_ptr->next;
|
|
||||||
PlayStream (sound_sample,
|
|
||||||
SPEECH_SOURCE, AL_FALSE,
|
|
||||||
speechVolumeScale != 0.0f, AL_TRUE);
|
|
||||||
}
|
|
||||||
UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
|
||||||
}
|
|
||||||
//no_voice = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// processes sound data to oscilloscope
|
|
||||||
int
|
|
||||||
GetSoundData (void *data)
|
|
||||||
{
|
|
||||||
if (speechVolumeScale != 0.0f)
|
|
||||||
{
|
|
||||||
// speech is enabled
|
|
||||||
|
|
||||||
LockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
|
||||||
if (soundSource[SPEECH_SOURCE].sample && soundSource[SPEECH_SOURCE].sample->decoder &&
|
|
||||||
PlayingStream (SPEECH_SOURCE) && soundSource[SPEECH_SOURCE].sbuffer &&
|
|
||||||
soundSource[SPEECH_SOURCE].sbuf_size > 0)
|
|
||||||
{
|
|
||||||
float played_time = (GetTimeCounter () - soundSource[SPEECH_SOURCE].sbuf_lasttime) /
|
|
||||||
(float)ONE_SECOND;
|
|
||||||
int delta = (int) (played_time * (float)soundSource[SPEECH_SOURCE].
|
|
||||||
sample->decoder->frequency * 2.0f);
|
|
||||||
unsigned long pos, i;
|
|
||||||
UBYTE *scopedata = (UBYTE *) data;
|
|
||||||
UBYTE *sbuffer = soundSource[SPEECH_SOURCE].sbuffer;
|
|
||||||
|
|
||||||
assert (soundSource[SPEECH_SOURCE].sample->decoder->frequency == 11025);
|
|
||||||
assert (soundSource[SPEECH_SOURCE].sample->decoder->format == AL_FORMAT_MONO16);
|
|
||||||
|
|
||||||
if (delta < 0)
|
|
||||||
{
|
|
||||||
//fprintf (stderr, "GetSoundData(): something's messed with timing, delta %d\n", delta);
|
|
||||||
delta = 0;
|
|
||||||
}
|
|
||||||
else if (delta > (int)(soundSource[SPEECH_SOURCE].sbuf_size * 2))
|
|
||||||
{
|
|
||||||
//fprintf (stderr, "GetSoundData(): something's messed with timing, delta %d\n", delta);
|
|
||||||
delta = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//fprintf (stderr, "played_data %d total_decoded %d delta %d\n", played_data, soundSource[SPEECH_SOURCE].total_decoded, delta);
|
|
||||||
|
|
||||||
pos = soundSource[SPEECH_SOURCE].sbuf_offset + delta;
|
|
||||||
if (pos % 2 == 1)
|
|
||||||
pos++;
|
|
||||||
|
|
||||||
assert (pos >= 0);
|
|
||||||
|
|
||||||
for (i = 0; i < RADAR_WIDTH; ++i)
|
|
||||||
{
|
|
||||||
SDWORD s;
|
|
||||||
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
if (pos >= soundSource[SPEECH_SOURCE].sbuf_size)
|
|
||||||
pos = pos - soundSource[SPEECH_SOURCE].sbuf_size;
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
s = *(SWORD*) (&sbuffer[pos]);
|
|
||||||
s = (s / 1260) + (RADAR_HEIGHT >> 1);
|
|
||||||
if (s < 0)
|
|
||||||
s = 0;
|
|
||||||
else if (s >= RADAR_HEIGHT)
|
|
||||||
s = RADAR_HEIGHT - 1;
|
|
||||||
scopedata[i] = (UBYTE) s;
|
|
||||||
|
|
||||||
pos += 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
|
||||||
}
|
|
||||||
else if (musicVolumeScale != 0.0f)
|
|
||||||
{
|
|
||||||
// speech is disabled but music is not so process it instead
|
|
||||||
|
|
||||||
LockMutex (soundSource[MUSIC_SOURCE].stream_mutex);
|
|
||||||
if (soundSource[MUSIC_SOURCE].sample && soundSource[MUSIC_SOURCE].sample->decoder &&
|
|
||||||
PlayingStream (MUSIC_SOURCE) && soundSource[MUSIC_SOURCE].sbuffer &&
|
|
||||||
soundSource[MUSIC_SOURCE].sbuf_size > 0)
|
|
||||||
{
|
|
||||||
float played_time = (GetTimeCounter () - soundSource[MUSIC_SOURCE].sbuf_lasttime) /
|
|
||||||
(float)ONE_SECOND;
|
|
||||||
int delta = (int) (played_time * (float)soundSource[MUSIC_SOURCE].
|
|
||||||
sample->decoder->frequency * 4.0f);
|
|
||||||
unsigned long pos, i, step;
|
|
||||||
UBYTE *scopedata = (UBYTE *) data;
|
|
||||||
UBYTE *sbuffer = soundSource[MUSIC_SOURCE].sbuffer;
|
|
||||||
|
|
||||||
assert (soundSource[MUSIC_SOURCE].sample->decoder->frequency >= 11025);
|
|
||||||
assert (soundSource[MUSIC_SOURCE].sample->decoder->format == AL_FORMAT_STEREO16);
|
|
||||||
|
|
||||||
step = soundSource[MUSIC_SOURCE].sample->decoder->frequency / 11025 * 16;
|
|
||||||
if (step % 2 == 1)
|
|
||||||
step++;
|
|
||||||
|
|
||||||
if (delta < 0)
|
|
||||||
{
|
|
||||||
//fprintf (stderr, "GetSoundData(): something's messed with timing, delta %d\n", delta);
|
|
||||||
delta = 0;
|
|
||||||
}
|
|
||||||
else if (delta > (int)(soundSource[MUSIC_SOURCE].sbuf_size * 2))
|
|
||||||
{
|
|
||||||
//fprintf (stderr, "GetSoundData(): something's messed with timing, delta %d\n", delta);
|
|
||||||
delta = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//fprintf (stderr, "played_data %d total_decoded %d delta %d\n", played_data, soundSource[MUSIC_SOURCE].total_decoded, delta);
|
|
||||||
|
|
||||||
pos = soundSource[MUSIC_SOURCE].sbuf_offset + delta;
|
|
||||||
if (pos % 2 == 1)
|
|
||||||
pos++;
|
|
||||||
|
|
||||||
assert (pos >= 0);
|
|
||||||
|
|
||||||
for (i = 0; i < RADAR_WIDTH; ++i)
|
|
||||||
{
|
|
||||||
SDWORD s;
|
|
||||||
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
if (pos >= soundSource[MUSIC_SOURCE].sbuf_size)
|
|
||||||
pos = pos - soundSource[MUSIC_SOURCE].sbuf_size;
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
s = (*(SWORD*)(&sbuffer[pos])) + (*(SWORD*)(&sbuffer[pos + 2]));
|
|
||||||
|
|
||||||
s = (s / 1260) + (RADAR_HEIGHT >> 1);
|
|
||||||
if (s < 0)
|
|
||||||
s = 0;
|
|
||||||
else if (s >= RADAR_HEIGHT)
|
|
||||||
s = RADAR_HEIGHT - 1;
|
|
||||||
scopedata[i] = (UBYTE) s;
|
|
||||||
|
|
||||||
pos += step;
|
|
||||||
}
|
|
||||||
|
|
||||||
UnlockMutex (soundSource[MUSIC_SOURCE].stream_mutex);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
UnlockMutex (soundSource[MUSIC_SOURCE].stream_mutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// tells current position of streaming speech
|
|
||||||
int
|
|
||||||
GetSoundInfo (int max_len)
|
|
||||||
{
|
|
||||||
ALuint length, offset;
|
|
||||||
LockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
|
||||||
if (soundSource[SPEECH_SOURCE].sample)
|
|
||||||
{
|
|
||||||
length = (ALuint) (soundSource[SPEECH_SOURCE].sample->length * (float)ONE_SECOND);
|
|
||||||
offset = (ALuint) (GetTimeCounter () - soundSource[SPEECH_SOURCE].start_time);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
|
||||||
if (offset > length)
|
|
||||||
return max_len;
|
|
||||||
return (int)(max_len * offset / length);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
/* OpenAL specific code by Mika Kolehmainen, 2002-10-23
|
/* OpenAL specific code by Mika Kolehmainen, 2002-10-23
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef SOUNDMODULE_MIXSDL
|
#if defined SOUNDMODULE_MIXSDL || defined SOUNDMODULE_OPENAL
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
#include <io.h>
|
#include <io.h>
|
||||||
@@ -33,24 +33,24 @@ PlayChannel (COUNT channel, PVOID sample, COUNT sample_length, COUNT loop_begin,
|
|||||||
{
|
{
|
||||||
TFB_SoundSample *tfb_sample = *(TFB_SoundSample**) sample;
|
TFB_SoundSample *tfb_sample = *(TFB_SoundSample**) sample;
|
||||||
soundSource[channel].sample = tfb_sample;
|
soundSource[channel].sample = tfb_sample;
|
||||||
mixSDL_SourceRewind (soundSource[channel].handle);
|
TFBSound_SourceRewind (soundSource[channel].handle);
|
||||||
mixSDL_Sourcei (soundSource[channel].handle, MIX_BUFFER, tfb_sample->buffer[0]);
|
TFBSound_Sourcei (soundSource[channel].handle, TFBSOUND_BUFFER, tfb_sample->buffer[0]);
|
||||||
mixSDL_SourcePlay (soundSource[channel].handle);
|
TFBSound_SourcePlay (soundSource[channel].handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
StopChannel(COUNT channel, unsigned char Priority)
|
StopChannel(COUNT channel, unsigned char Priority)
|
||||||
{
|
{
|
||||||
mixSDL_SourceRewind (soundSource[channel].handle);
|
TFBSound_SourceRewind (soundSource[channel].handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
ChannelPlaying (COUNT WhichChannel)
|
ChannelPlaying (COUNT WhichChannel)
|
||||||
{
|
{
|
||||||
mixSDL_Object state;
|
TFBSound_Object state;
|
||||||
|
|
||||||
mixSDL_GetSourcei (soundSource[WhichChannel].handle, MIX_SOURCE_STATE, &state);
|
TFBSound_GetSourcei (soundSource[WhichChannel].handle, TFBSOUND_SOURCE_STATE, &state);
|
||||||
if (state == MIX_PLAYING)
|
if (state == TFBSOUND_PLAYING)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
@@ -60,7 +60,7 @@ SetChannelVolume (COUNT channel, COUNT volume, BYTE priority)
|
|||||||
// I wonder what this whole priority business is...
|
// I wonder what this whole priority business is...
|
||||||
// I can probably ignore it.
|
// I can probably ignore it.
|
||||||
{
|
{
|
||||||
mixSDL_Sourcef (soundSource[channel].handle, MIX_GAIN,
|
TFBSound_Sourcef (soundSource[channel].handle, TFBSOUND_GAIN,
|
||||||
(volume / (float)MAX_VOLUME) * sfxVolumeScale);
|
(volume / (float)MAX_VOLUME) * sfxVolumeScale);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,10 +152,10 @@ _GetSoundBankData (FILE *fp, DWORD length)
|
|||||||
//fprintf (stderr, "_GetSoundBankData(): decoded_bytes %d\n", decoded_bytes);
|
//fprintf (stderr, "_GetSoundBankData(): decoded_bytes %d\n", decoded_bytes);
|
||||||
|
|
||||||
sndfx[snd_ct]->num_buffers = 1;
|
sndfx[snd_ct]->num_buffers = 1;
|
||||||
sndfx[snd_ct]->buffer = (mixSDL_Object *) HMalloc (
|
sndfx[snd_ct]->buffer = (TFBSound_Object *) HMalloc (
|
||||||
sizeof (mixSDL_Object) * sndfx[snd_ct]->num_buffers);
|
sizeof (TFBSound_Object) * sndfx[snd_ct]->num_buffers);
|
||||||
mixSDL_GenBuffers (sndfx[snd_ct]->num_buffers, sndfx[snd_ct]->buffer);
|
TFBSound_GenBuffers (sndfx[snd_ct]->num_buffers, sndfx[snd_ct]->buffer);
|
||||||
mixSDL_BufferData (sndfx[snd_ct]->buffer[0], sndfx[snd_ct]->decoder->format,
|
TFBSound_BufferData (sndfx[snd_ct]->buffer[0], sndfx[snd_ct]->decoder->format,
|
||||||
sndfx[snd_ct]->decoder->buffer, decoded_bytes,
|
sndfx[snd_ct]->decoder->buffer, decoded_bytes,
|
||||||
sndfx[snd_ct]->decoder->frequency);
|
sndfx[snd_ct]->decoder->frequency);
|
||||||
|
|
||||||
@@ -246,7 +246,7 @@ _ReleaseSoundBankData (MEM_HANDLE Snd)
|
|||||||
|
|
||||||
if ((*sptr)->decoder)
|
if ((*sptr)->decoder)
|
||||||
SoundDecoder_Free ((*sptr)->decoder);
|
SoundDecoder_Free ((*sptr)->decoder);
|
||||||
mixSDL_DeleteBuffers ((*sptr)->num_buffers, (*sptr)->buffer);
|
TFBSound_DeleteBuffers ((*sptr)->num_buffers, (*sptr)->buffer);
|
||||||
HFree ((*sptr)->buffer);
|
HFree ((*sptr)->buffer);
|
||||||
HFree (*sptr);
|
HFree (*sptr);
|
||||||
*sptr++ = 0;
|
*sptr++ = 0;
|
||||||
@@ -0,0 +1,140 @@
|
|||||||
|
//Copyright Paul Reiche, Fred Ford. 1992-2002
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined SOUNDMODULE_MIXSDL || defined SOUNDMODULE_OPENAL
|
||||||
|
|
||||||
|
#include "libs/sound/sound_common.h"
|
||||||
|
#include "sound.h"
|
||||||
|
|
||||||
|
TFB_SoundSource soundSource[NUM_SOUNDSOURCES];
|
||||||
|
static Task StreamDecoderTask;
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
StopSound (void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = FIRST_SFX_SOURCE; i <= LAST_SFX_SOURCE; ++i)
|
||||||
|
{
|
||||||
|
TFBSound_SourceRewind (soundSource[i].handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
SoundPlaying (void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < NUM_SOUNDSOURCES; ++i)
|
||||||
|
{
|
||||||
|
TFB_SoundSample *sample;
|
||||||
|
sample = soundSource[i].sample;
|
||||||
|
if (sample && sample->decoder)
|
||||||
|
{
|
||||||
|
BOOLEAN result;
|
||||||
|
LockMutex (soundSource[i].stream_mutex);
|
||||||
|
result = PlayingStream (i);
|
||||||
|
UnlockMutex (soundSource[i].stream_mutex);
|
||||||
|
if (result)
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uint32 state;
|
||||||
|
TFBSound_GetSourcei (soundSource[i].handle, TFBSOUND_SOURCE_STATE, &state);
|
||||||
|
if (state == TFBSOUND_PLAYING)
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
TFB_SoundChain *
|
||||||
|
create_soundchain (TFB_SoundDecoder *decoder, float startTime)
|
||||||
|
{
|
||||||
|
TFB_SoundChain *chain;
|
||||||
|
chain = (TFB_SoundChain *)HMalloc (sizeof (TFB_SoundChain));
|
||||||
|
chain->decoder = decoder;
|
||||||
|
chain->next =NULL;
|
||||||
|
chain->start_time = startTime;
|
||||||
|
chain->tag.buf_name = 0;
|
||||||
|
chain->tag.type = 0;
|
||||||
|
return (chain);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
destroy_soundchain (TFB_SoundChain *chain)
|
||||||
|
{
|
||||||
|
while (chain->next)
|
||||||
|
{
|
||||||
|
TFB_SoundChain *tmp_chain = chain->next;
|
||||||
|
chain->next = chain->next->next;
|
||||||
|
if (tmp_chain->decoder)
|
||||||
|
SoundDecoder_Free (tmp_chain->decoder);
|
||||||
|
HFree (tmp_chain);
|
||||||
|
}
|
||||||
|
SoundDecoder_Free (chain->decoder);
|
||||||
|
HFree (chain);
|
||||||
|
}
|
||||||
|
|
||||||
|
TFB_SoundChain *
|
||||||
|
get_previous_chain (TFB_SoundChain *first_chain, TFB_SoundChain *current_chain)
|
||||||
|
{
|
||||||
|
TFB_SoundChain *prev_chain;
|
||||||
|
prev_chain = first_chain;
|
||||||
|
if (prev_chain == current_chain)
|
||||||
|
return (prev_chain);
|
||||||
|
while (prev_chain->next)
|
||||||
|
{
|
||||||
|
if (prev_chain->next == current_chain)
|
||||||
|
return (prev_chain);
|
||||||
|
prev_chain = prev_chain->next;
|
||||||
|
}
|
||||||
|
return (first_chain);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Status: Ignored
|
||||||
|
BOOLEAN
|
||||||
|
InitSound (int argc, char* argv[])
|
||||||
|
{
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Status: Ignored
|
||||||
|
void
|
||||||
|
UninitSound (void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetSFXVolume (float volume)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = FIRST_SFX_SOURCE; i <= LAST_SFX_SOURCE; ++i)
|
||||||
|
{
|
||||||
|
TFBSound_Sourcef (soundSource[i].handle, TFBSOUND_GAIN, volume);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetSpeechVolume (float volume)
|
||||||
|
{
|
||||||
|
TFBSound_Sourcef (soundSource[SPEECH_SOURCE].handle, TFBSOUND_GAIN, volume);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -22,7 +22,11 @@
|
|||||||
#include "libs/strings/strintrn.h"
|
#include "libs/strings/strintrn.h"
|
||||||
#include "libs/sound/sndintrn.h"
|
#include "libs/sound/sndintrn.h"
|
||||||
#include "libs/sound/sound_common.h"
|
#include "libs/sound/sound_common.h"
|
||||||
#include "mixer.h"
|
#if defined SOUNDMODULE_MIXSDL
|
||||||
|
#include "mixsdl/sound_mixsdl.h"
|
||||||
|
#elif defined SOUNDMODULE_OPENAL
|
||||||
|
#include "openal/sound_openal.h"
|
||||||
|
#endif
|
||||||
#include "libs/sound/decoders/decoder.h"
|
#include "libs/sound/decoders/decoder.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -35,7 +39,7 @@
|
|||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
mixSDL_Object buf_name;
|
TFBSound_Object buf_name;
|
||||||
int type;
|
int type;
|
||||||
void *value;
|
void *value;
|
||||||
} TFB_SoundTag;
|
} TFB_SoundTag;
|
||||||
@@ -61,7 +65,7 @@ typedef struct tfb_soundsample
|
|||||||
TFB_SoundChain *read_chain_ptr; // points to chain read poistion
|
TFB_SoundChain *read_chain_ptr; // points to chain read poistion
|
||||||
TFB_SoundChain *play_chain_ptr; // points to chain playing position
|
TFB_SoundChain *play_chain_ptr; // points to chain playing position
|
||||||
float length; // total length of decoder chain in seconds
|
float length; // total length of decoder chain in seconds
|
||||||
mixSDL_Object *buffer;
|
TFBSound_Object *buffer;
|
||||||
uint32 num_buffers;
|
uint32 num_buffers;
|
||||||
TFB_SoundTag **buffer_tag;
|
TFB_SoundTag **buffer_tag;
|
||||||
} TFB_SoundSample;
|
} TFB_SoundSample;
|
||||||
@@ -70,7 +74,7 @@ typedef struct tfb_soundsample
|
|||||||
typedef struct tfb_soundsource
|
typedef struct tfb_soundsource
|
||||||
{
|
{
|
||||||
TFB_SoundSample *sample;
|
TFB_SoundSample *sample;
|
||||||
mixSDL_Object handle;
|
TFBSound_Object handle;
|
||||||
bool stream_should_be_playing;
|
bool stream_should_be_playing;
|
||||||
Mutex stream_mutex;
|
Mutex stream_mutex;
|
||||||
sint32 start_time;
|
sint32 start_time;
|
||||||
@@ -17,11 +17,10 @@
|
|||||||
/* By Mika Kolehmainen, 2002-10-23
|
/* By Mika Kolehmainen, 2002-10-23
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef SOUNDMODULE_MIXSDL
|
#if defined SOUNDMODULE_MIXSDL || defined SOUNDMODULE_OPENAL
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include "sound.h"
|
#include "sound.h"
|
||||||
#include "mixer.h"
|
|
||||||
|
|
||||||
bool speech_advancetrack = FALSE;
|
bool speech_advancetrack = FALSE;
|
||||||
|
|
||||||
@@ -49,7 +48,7 @@ PlayStream (TFB_SoundSample *sample, uint32 source, bool looping, bool scope, bo
|
|||||||
soundSource[source].sample = sample;
|
soundSource[source].sample = sample;
|
||||||
soundSource[source].sample->play_chain_ptr = sample->read_chain_ptr;
|
soundSource[source].sample->play_chain_ptr = sample->read_chain_ptr;
|
||||||
soundSource[source].sample->decoder->looping = looping;
|
soundSource[source].sample->decoder->looping = looping;
|
||||||
mixSDL_Sourcei (soundSource[source].handle, MIX_LOOPING, false);
|
TFBSound_Sourcei (soundSource[source].handle, TFBSOUND_LOOPING, false);
|
||||||
|
|
||||||
if (scope)
|
if (scope)
|
||||||
{
|
{
|
||||||
@@ -73,9 +72,9 @@ PlayStream (TFB_SoundSample *sample, uint32 source, bool looping, bool scope, bo
|
|||||||
if (decoded_bytes == 0)
|
if (decoded_bytes == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
mixSDL_BufferData (sample->buffer[i], sample->decoder->format, sample->decoder->buffer,
|
TFBSound_BufferData (sample->buffer[i], sample->decoder->format, sample->decoder->buffer,
|
||||||
decoded_bytes, sample->decoder->frequency);
|
decoded_bytes, sample->decoder->frequency);
|
||||||
mixSDL_SourceQueueBuffers (soundSource[source].handle, 1, &sample->buffer[i]);
|
TFBSound_SourceQueueBuffers (soundSource[source].handle, 1, &sample->buffer[i]);
|
||||||
|
|
||||||
if (scope)
|
if (scope)
|
||||||
{
|
{
|
||||||
@@ -114,7 +113,7 @@ PlayStream (TFB_SoundSample *sample, uint32 source, bool looping, bool scope, bo
|
|||||||
soundSource[source].sbuf_lasttime = GetTimeCounter ();
|
soundSource[source].sbuf_lasttime = GetTimeCounter ();
|
||||||
soundSource[source].start_time = (sint32)GetTimeCounter () - offset;
|
soundSource[source].start_time = (sint32)GetTimeCounter () - offset;
|
||||||
soundSource[source].stream_should_be_playing = TRUE;
|
soundSource[source].stream_should_be_playing = TRUE;
|
||||||
mixSDL_SourcePlay (soundSource[source].handle);
|
TFBSound_SourcePlay (soundSource[source].handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -136,16 +135,16 @@ StopStream (uint32 source)
|
|||||||
soundSource[source].sbuf_size = 0;
|
soundSource[source].sbuf_size = 0;
|
||||||
soundSource[source].sbuf_offset = 0;
|
soundSource[source].sbuf_offset = 0;
|
||||||
|
|
||||||
mixSDL_SourceStop (soundSource[source].handle);
|
TFBSound_SourceStop (soundSource[source].handle);
|
||||||
mixSDL_GetSourcei (soundSource[source].handle, MIX_BUFFERS_PROCESSED, &processed);
|
TFBSound_GetSourcei (soundSource[source].handle, TFBSOUND_BUFFERS_PROCESSED, &processed);
|
||||||
mixSDL_GetSourcei (soundSource[source].handle, MIX_BUFFERS_QUEUED, &queued);
|
TFBSound_GetSourcei (soundSource[source].handle, TFBSOUND_BUFFERS_QUEUED, &queued);
|
||||||
|
|
||||||
//fprintf (stderr, "StopStream(): source %d processed %d queued %d num_buffers %d\n", source, processed, queued, soundSource[source].sample->num_buffers);
|
//fprintf (stderr, "StopStream(): source %d processed %d queued %d num_buffers %d\n", source, processed, queued, soundSource[source].sample->num_buffers);
|
||||||
|
|
||||||
if (processed != 0)
|
if (processed != 0)
|
||||||
{
|
{
|
||||||
buffer = (uint32 *) HMalloc (sizeof (uint32) * processed);
|
buffer = (uint32 *) HMalloc (sizeof (uint32) * processed);
|
||||||
mixSDL_SourceUnqueueBuffers (soundSource[source].handle, processed, buffer);
|
TFBSound_SourceUnqueueBuffers (soundSource[source].handle, processed, buffer);
|
||||||
HFree (buffer);
|
HFree (buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -155,7 +154,7 @@ PauseStream (uint32 source)
|
|||||||
{
|
{
|
||||||
// TODO: how to handle start_time
|
// TODO: how to handle start_time
|
||||||
soundSource[source].stream_should_be_playing = FALSE;
|
soundSource[source].stream_should_be_playing = FALSE;
|
||||||
mixSDL_SourcePause (soundSource[source].handle);
|
TFBSound_SourcePause (soundSource[source].handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -163,7 +162,7 @@ ResumeStream (uint32 source)
|
|||||||
{
|
{
|
||||||
// TODO: how to handle start_time
|
// TODO: how to handle start_time
|
||||||
soundSource[source].stream_should_be_playing = TRUE;
|
soundSource[source].stream_should_be_playing = TRUE;
|
||||||
mixSDL_SourcePlay (soundSource[source].handle);
|
TFBSound_SourcePlay (soundSource[source].handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
@@ -177,7 +176,7 @@ StreamDecoderTaskFunc (void *data)
|
|||||||
{
|
{
|
||||||
Task task = (Task)data;
|
Task task = (Task)data;
|
||||||
int i;
|
int i;
|
||||||
mixSDL_Object last_buffer[NUM_SOUNDSOURCES];
|
TFBSound_Object last_buffer[NUM_SOUNDSOURCES];
|
||||||
|
|
||||||
for (i = 0; i < NUM_SOUNDSOURCES; i++)
|
for (i = 0; i < NUM_SOUNDSOURCES; i++)
|
||||||
last_buffer[i] = 0;
|
last_buffer[i] = 0;
|
||||||
@@ -190,7 +189,7 @@ StreamDecoderTaskFunc (void *data)
|
|||||||
for (i = MUSIC_SOURCE; i < NUM_SOUNDSOURCES; ++i)
|
for (i = MUSIC_SOURCE; i < NUM_SOUNDSOURCES; ++i)
|
||||||
{
|
{
|
||||||
uint32 processed, queued;
|
uint32 processed, queued;
|
||||||
mixSDL_Object state;
|
TFBSound_Object state;
|
||||||
bool do_speech_advancetrack = false;
|
bool do_speech_advancetrack = false;
|
||||||
|
|
||||||
LockMutex (soundSource[i].stream_mutex);
|
LockMutex (soundSource[i].stream_mutex);
|
||||||
@@ -204,13 +203,13 @@ StreamDecoderTaskFunc (void *data)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
mixSDL_GetSourcei (soundSource[i].handle, MIX_BUFFERS_PROCESSED, &processed);
|
TFBSound_GetSourcei (soundSource[i].handle, TFBSOUND_BUFFERS_PROCESSED, &processed);
|
||||||
mixSDL_GetSourcei (soundSource[i].handle, MIX_BUFFERS_QUEUED, &queued);
|
TFBSound_GetSourcei (soundSource[i].handle, TFBSOUND_BUFFERS_QUEUED, &queued);
|
||||||
|
|
||||||
if (processed == 0)
|
if (processed == 0)
|
||||||
{
|
{
|
||||||
mixSDL_GetSourcei (soundSource[i].handle, MIX_SOURCE_STATE, &state);
|
TFBSound_GetSourcei (soundSource[i].handle, TFBSOUND_SOURCE_STATE, &state);
|
||||||
if (state != MIX_PLAYING)
|
if (state != TFBSOUND_PLAYING)
|
||||||
{
|
{
|
||||||
if (queued == 0 && soundSource[i].sample->decoder->error == SOUNDDECODER_EOF)
|
if (queued == 0 && soundSource[i].sample->decoder->error == SOUNDDECODER_EOF)
|
||||||
{
|
{
|
||||||
@@ -228,7 +227,7 @@ StreamDecoderTaskFunc (void *data)
|
|||||||
{
|
{
|
||||||
fprintf (stderr, "StreamDecoderTaskFunc(): buffer underrun when playing %s, source %d\n",
|
fprintf (stderr, "StreamDecoderTaskFunc(): buffer underrun when playing %s, source %d\n",
|
||||||
soundSource[i].sample->decoder->filename, i);
|
soundSource[i].sample->decoder->filename, i);
|
||||||
mixSDL_SourcePlay (soundSource[i].handle);
|
TFBSound_SourcePlay (soundSource[i].handle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -238,15 +237,15 @@ StreamDecoderTaskFunc (void *data)
|
|||||||
while (processed)
|
while (processed)
|
||||||
{
|
{
|
||||||
uint32 error;
|
uint32 error;
|
||||||
mixSDL_Object buffer;
|
TFBSound_Object buffer;
|
||||||
uint32 decoded_bytes;
|
uint32 decoded_bytes;
|
||||||
uint32 buf_num;
|
uint32 buf_num;
|
||||||
|
|
||||||
mixSDL_GetError (); // clear error state
|
TFBSound_GetError (); // clear error state
|
||||||
|
|
||||||
mixSDL_SourceUnqueueBuffers (soundSource[i].handle, 1, &buffer);
|
TFBSound_SourceUnqueueBuffers (soundSource[i].handle, 1, &buffer);
|
||||||
|
|
||||||
if ((error = mixSDL_GetError()) != MIX_NO_ERROR)
|
if ((error = TFBSound_GetError()) != TFBSOUND_NO_ERROR)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "StreamDecoderTaskFunc(): OpenAL error after alSourceUnqueueBuffers: %x, file %s, source %d\n", error, soundSource[i].sample->decoder->filename, i);
|
fprintf (stderr, "StreamDecoderTaskFunc(): OpenAL error after alSourceUnqueueBuffers: %x, file %s, source %d\n", error, soundSource[i].sample->decoder->filename, i);
|
||||||
break;
|
break;
|
||||||
@@ -271,7 +270,7 @@ StreamDecoderTaskFunc (void *data)
|
|||||||
{
|
{
|
||||||
uint32 buf_size;
|
uint32 buf_size;
|
||||||
soundSource[i].sbuf_lasttime = GetTimeCounter ();
|
soundSource[i].sbuf_lasttime = GetTimeCounter ();
|
||||||
mixSDL_GetBufferi(buffer, MIX_SIZE, &buf_size);
|
TFBSound_GetBufferi(buffer, TFBSOUND_SIZE, &buf_size);
|
||||||
soundSource[i].sbuf_offset += buf_size;
|
soundSource[i].sbuf_offset += buf_size;
|
||||||
if (soundSource[i].sbuf_offset > soundSource[i].sbuf_size)
|
if (soundSource[i].sbuf_offset > soundSource[i].sbuf_size)
|
||||||
soundSource[i].sbuf_offset -= soundSource[i].sbuf_size;
|
soundSource[i].sbuf_offset -= soundSource[i].sbuf_size;
|
||||||
@@ -330,19 +329,38 @@ StreamDecoderTaskFunc (void *data)
|
|||||||
|
|
||||||
if (decoded_bytes > 0)
|
if (decoded_bytes > 0)
|
||||||
{
|
{
|
||||||
mixSDL_BufferData (buffer, soundSource[i].sample->decoder->format,
|
#if defined SOUNDMODULE_OPENAL && !defined (WIN32) // && !defined (MacOS and BeOS too)
|
||||||
soundSource[i].sample->decoder->buffer, decoded_bytes,
|
// *nix OpenAL implementation has to handle stereo data differently to avoid mixing it to mono
|
||||||
soundSource[i].sample->decoder->frequency);
|
|
||||||
|
if (soundSource[i].sample->decoder->format == TFBSOUND_FORMAT_STEREO8 ||
|
||||||
if ((error = mixSDL_GetError()) != MIX_NO_ERROR)
|
soundSource[i].sample->decoder->format == TFBSOUND_FORMAT_STEREO16)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "StreamDecoderTaskFunc(): mixSDL error after mixSDL_BufferData: %x, file %s, source %d, decoded_bytes %d\n",
|
TFBSound_BufferData_Linux (buffer, soundSource[i].sample->decoder->format,
|
||||||
|
soundSource[i].sample->decoder->buffer, decoded_bytes,
|
||||||
|
soundSource[i].sample->decoder->frequency,
|
||||||
|
soundSource[i].sample->decoder->format);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TFBSound_BufferData (buffer, soundSource[i].sample->decoder->format,
|
||||||
|
soundSource[i].sample->decoder->buffer, decoded_bytes,
|
||||||
|
soundSource[i].sample->decoder->frequency);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
TFBSound_BufferData (buffer, soundSource[i].sample->decoder->format,
|
||||||
|
soundSource[i].sample->decoder->buffer, decoded_bytes,
|
||||||
|
soundSource[i].sample->decoder->frequency);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ((error = TFBSound_GetError()) != TFBSOUND_NO_ERROR)
|
||||||
|
{
|
||||||
|
fprintf (stderr, "StreamDecoderTaskFunc(): TFBSound error after TFBSound_BufferData: %x, file %s, source %d, decoded_bytes %d\n",
|
||||||
error, soundSource[i].sample->decoder->filename, i, decoded_bytes);
|
error, soundSource[i].sample->decoder->filename, i, decoded_bytes);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
last_buffer[i] = buffer;
|
last_buffer[i] = buffer;
|
||||||
mixSDL_SourceQueueBuffers (soundSource[i].handle, 1, &buffer);
|
TFBSound_SourceQueueBuffers (soundSource[i].handle, 1, &buffer);
|
||||||
|
|
||||||
if (soundSource[i].sbuffer)
|
if (soundSource[i].sbuffer)
|
||||||
{
|
{
|
||||||
@@ -380,9 +398,9 @@ StreamDecoderTaskFunc (void *data)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((error = mixSDL_GetError()) != MIX_NO_ERROR)
|
if ((error = TFBSound_GetError()) != TFBSOUND_NO_ERROR)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "StreamDecoderTaskFunc(): mixSDL error after mixSDL_SourceQueueBuffers: %x, file %s, source %d, decoded_bytes %d\n",
|
fprintf (stderr, "StreamDecoderTaskFunc(): TFBSound error after TFBSound_SourceQueueBuffers: %x, file %s, source %d, decoded_bytes %d\n",
|
||||||
error, i, soundSource[i].sample->decoder->filename, decoded_bytes);
|
error, i, soundSource[i].sample->decoder->filename, decoded_bytes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+9
-9
@@ -18,7 +18,7 @@
|
|||||||
* Adapted for MixSDL
|
* Adapted for MixSDL
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef SOUNDMODULE_MIXSDL
|
#if defined SOUNDMODULE_MIXSDL || defined SOUNDMODULE_OPENAL
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include "sound.h"
|
#include "sound.h"
|
||||||
@@ -97,10 +97,10 @@ ResumeTrack ()
|
|||||||
uint32 state;
|
uint32 state;
|
||||||
|
|
||||||
LockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
LockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
||||||
mixSDL_GetSourcei (soundSource[SPEECH_SOURCE].handle, MIX_SOURCE_STATE, &state);
|
TFBSound_GetSourcei (soundSource[SPEECH_SOURCE].handle, TFBSOUND_SOURCE_STATE, &state);
|
||||||
|
|
||||||
if (!track_pos_changed && !soundSource[SPEECH_SOURCE].stream_should_be_playing &&
|
if (!track_pos_changed && !soundSource[SPEECH_SOURCE].stream_should_be_playing &&
|
||||||
state == MIX_PAUSED)
|
state == TFBSOUND_PAUSED)
|
||||||
{
|
{
|
||||||
ResumeStream (SPEECH_SOURCE);
|
ResumeStream (SPEECH_SOURCE);
|
||||||
UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
|
||||||
@@ -172,7 +172,7 @@ StopTrack ()
|
|||||||
if (sound_sample)
|
if (sound_sample)
|
||||||
{
|
{
|
||||||
DestroyMutex (track_mutex);
|
DestroyMutex (track_mutex);
|
||||||
mixSDL_DeleteBuffers (sound_sample->num_buffers, sound_sample->buffer);
|
TFBSound_DeleteBuffers (sound_sample->num_buffers, sound_sample->buffer);
|
||||||
HFree (sound_sample->buffer);
|
HFree (sound_sample->buffer);
|
||||||
HFree (sound_sample->buffer_tag);
|
HFree (sound_sample->buffer_tag);
|
||||||
HFree (sound_sample);
|
HFree (sound_sample);
|
||||||
@@ -369,7 +369,7 @@ SpliceTrack (UNICODE *TrackName, UNICODE *TrackText, UNICODE *TimeStamp)
|
|||||||
sound_sample->num_buffers = 8;
|
sound_sample->num_buffers = 8;
|
||||||
sound_sample->buffer_tag = HMalloc (sizeof (TFB_SoundTag *) * sound_sample->num_buffers);
|
sound_sample->buffer_tag = HMalloc (sizeof (TFB_SoundTag *) * sound_sample->num_buffers);
|
||||||
sound_sample->buffer = HMalloc (sizeof (uint32) * sound_sample->num_buffers);
|
sound_sample->buffer = HMalloc (sizeof (uint32) * sound_sample->num_buffers);
|
||||||
mixSDL_GenBuffers (sound_sample->num_buffers, sound_sample->buffer);
|
TFBSound_GenBuffers (sound_sample->num_buffers, sound_sample->buffer);
|
||||||
decoder = SoundDecoder_Load (TrackName, 4096, startTime, time_stamps[cur_page]);
|
decoder = SoundDecoder_Load (TrackName, 4096, startTime, time_stamps[cur_page]);
|
||||||
sound_sample->read_chain_ptr = create_soundchain (decoder, 0.0);
|
sound_sample->read_chain_ptr = create_soundchain (decoder, 0.0);
|
||||||
sound_sample->decoder = decoder;
|
sound_sample->decoder = decoder;
|
||||||
@@ -404,7 +404,7 @@ SpliceTrack (UNICODE *TrackName, UNICODE *TrackText, UNICODE *TimeStamp)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
fprintf (stderr, "SpliceTrack(): couldn't load %s\n", TrackName);
|
fprintf (stderr, "SpliceTrack(): couldn't load %s\n", TrackName);
|
||||||
mixSDL_DeleteBuffers (sound_sample->num_buffers, sound_sample->buffer);
|
TFBSound_DeleteBuffers (sound_sample->num_buffers, sound_sample->buffer);
|
||||||
destroy_soundchain (first_chain);
|
destroy_soundchain (first_chain);
|
||||||
first_chain = NULL;
|
first_chain = NULL;
|
||||||
HFree (sound_sample->buffer);
|
HFree (sound_sample->buffer);
|
||||||
@@ -554,11 +554,11 @@ GetSoundData (void *data)
|
|||||||
UBYTE *sbuffer = soundSource[SPEECH_SOURCE].sbuffer;
|
UBYTE *sbuffer = soundSource[SPEECH_SOURCE].sbuffer;
|
||||||
|
|
||||||
assert (soundSource[SPEECH_SOURCE].sample->decoder->frequency == 11025);
|
assert (soundSource[SPEECH_SOURCE].sample->decoder->frequency == 11025);
|
||||||
assert (soundSource[SPEECH_SOURCE].sample->decoder->format == MIX_FORMAT_MONO16);
|
assert (soundSource[SPEECH_SOURCE].sample->decoder->format == TFBSOUND_FORMAT_MONO16);
|
||||||
|
|
||||||
if (delta < 0)
|
if (delta < 0)
|
||||||
{
|
{
|
||||||
//fprintf (stderr, "GetSoundData(): something's messed with timing, delta %d\n", delta);
|
fprintf (stderr, "GetSoundData(): something's messed with timing, delta %d\n", delta);
|
||||||
delta = 0;
|
delta = 0;
|
||||||
}
|
}
|
||||||
else if (delta > (int)(soundSource[SPEECH_SOURCE].sbuf_size * 2))
|
else if (delta > (int)(soundSource[SPEECH_SOURCE].sbuf_size * 2))
|
||||||
@@ -622,7 +622,7 @@ GetSoundData (void *data)
|
|||||||
UBYTE *sbuffer = soundSource[MUSIC_SOURCE].sbuffer;
|
UBYTE *sbuffer = soundSource[MUSIC_SOURCE].sbuffer;
|
||||||
|
|
||||||
assert (soundSource[MUSIC_SOURCE].sample->decoder->frequency >= 11025);
|
assert (soundSource[MUSIC_SOURCE].sample->decoder->frequency >= 11025);
|
||||||
assert (soundSource[MUSIC_SOURCE].sample->decoder->format == MIX_FORMAT_STEREO16);
|
assert (soundSource[MUSIC_SOURCE].sample->decoder->format == TFBSOUND_FORMAT_STEREO16);
|
||||||
|
|
||||||
step = soundSource[MUSIC_SOURCE].sample->decoder->frequency / 11025 * 16;
|
step = soundSource[MUSIC_SOURCE].sample->decoder->frequency / 11025 * 16;
|
||||||
if (step % 2 == 1)
|
if (step % 2 == 1)
|
||||||
Reference in New Issue
Block a user