OpenAL sound code (default now instead of SDL_mixer), some misc fixes

git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@141 8092fc87-c524-0410-9efc-e669fe64eaf9
This commit is contained in:
gewlitys
2002-10-24 00:52:51 +00:00
parent f8a08fc120
commit 4e0638ed08
25 changed files with 1461 additions and 68 deletions
+10 -6
View File
@@ -33,15 +33,19 @@ SDL-image
Homepage: http://www.libsdl.org/projects/SDL_image/
Download: http://www.libsdl.org/projects/SDL_image/release/
SDL-mixer
A sound mixing library used with SDL.
Homepage: http://www.libsdl.org/projects/SDL_mixer/
Download: http://www.libsdl.org/projects/SDL_mixer/release/
SDL-sound
A sound loader library used with SDL.
An audio format decoder library.
Homepage: http://www.icculus.org/SDL_sound/
Download: http://www.icculus.org/SDL_sound/downloads/
Win32 users maybe need to get few updated dll's from: http://www.cc.jyu.fi/~mimakole/sc2/sdl_sound_dlls.zip
If compiling this yourself, be sure ogg vorbis and libmikmod (or libmodplug) support is compiled in.
OpenAL
A cross-platform spatialized audio library.
Homepage: http://www.openal.org
Linux download via CVS: http://opensource.creative.com
Win32 SDK download: http://ftp://opensource.creative.com/pub/sdk/OpenALSDK.exe
If you find these aren't enough, or if you know the names
of the corresponding RPM etc. packages, please report to
+19 -4
View File
@@ -67,6 +67,25 @@ Glitches (don't crash the game, medium priority):
crash anymore. This means the memory will not be freed until after the
complete battle (not just one fight). There's no permanent memory leak
though.
- OpenAL sound code problems:
- On Linux, volume control (AL_GAIN) doesn't work for streams.
This prevents also music fade in/out from working.
Most probably this is a Linux OpenAL implementation bug itself, and
authors have been informed.
- Occasional clipping/popping/etc artifacts
- Maybe caused by buggy soundcard drivers also
- Some unimplemented functions (for oscilloscope and dialogue seeking)
- Occasionally some speech oggs don't play
- When mod music is looping, there's some volume fade at the end of tune,
then it starts playing again. Should this happen? (modplug only?)
- Stock SDL_sound package for VC is outdated and win32 users have to get
few new .dll's to ensure proper operation
- Perhaps we should integrate mikmod to our code and use vorbis libs
directly to avoid depending on SDL_sound at all?
- If OpenAL causes too many problems, reverting to SDL_mixer is easy as
all code is preserved related to that, etc.. but SDL_mixer is pretty
sucky for various reasons so I'd like to avoid that.
Implementation bugs (low priority):
- The main thread is still created by a direct all to the SDL function,
@@ -137,7 +156,3 @@ Questions:
which we can free when no more memory is available, to allow an emergency
save.
- How about an ISO image for a self-contained linux CD which boots into SC2?
- SDL_mixer really doesn't seem to meet our needs.. should we
a) write our own mixing routines
b) look for alternatives (OpenAL perhaps?)
c) what?
+5 -5
View File
@@ -27,8 +27,8 @@ AM_MAINTAINER_MODE
# Configurables
CFLAGS="$CFLAGS -g -W -Wall -DHAVE_OPENGL -DSDL_PTHREADS -DGFXMODULE_SDL -DSOUNDMODULE_SDL"
CPPFLAGS="$CPPFLAGS -g -W -Wall -DHAVE_OPENGL -DSDL_PTHREADS -DGFXMODULE_SDL -DSOUNDMODULE_SDL"
CFLAGS="$CFLAGS -g -W -Wall -DHAVE_OPENGL -DSDL_PTHREADS -DGFXMODULE_SDL -DSOUNDMODULE_OPENAL"
CPPFLAGS="$CPPFLAGS -g -W -Wall -DHAVE_OPENGL -DSDL_PTHREADS -DGFXMODULE_SDL -DSOUNDMODULE_OPENAL"
# --------------------------------------------------------------------------
@@ -68,11 +68,11 @@ AC_CHECK_FUNCS([strupr])
# Check for SDL
SDL_VERSION=1.2.2
AM_PATH_SDL($SDL_VERSION, , AC_MSG_ERROR([*** SDL version $SDL_VERSION not found!]))
AC_CHECK_LIB(SDL_mixer, main, , AC_MSG_ERROR([Your system is missing libSDL_mixer!]),`sdl-config --libs`)
AC_CHECK_LIB(SDL_image, main, , AC_MSG_ERROR([Your system is missing libSDL_image!]),`sdl-config --libs`)
AC_CHECK_LIB(SDL_sound, main, , AC_MSG_ERROR([Your system is missing libSDL_sound!]),`sdl-config --libs`)
AC_CHECK_LIB(openal, main, , AC_MSG_ERROR([Your system is missing libopenal!]),"-lm")
#AC_CHECK_LIB(SDL_mixer, main, , AC_MSG_ERROR([Your system is missing libSDL_mixer!]),`sdl-config --libs`)
#AC_CHECK_HEADERS(SDL/SDL_image.h, , AC_MSG_ERROR([Your system is missing SDL_image.h!]))
#AC_CHECK_HEADERS(SDL/SDL_mixer.h, , AC_MSG_ERROR([Your system is missing SDL_mixer.h!]))
# Select platform dependent OpenGL libs.. (tweak your platform here)
case "$target" in
@@ -211,7 +211,7 @@ AC_CONFIG_FILES([
src/sc2code/libs/input/Makefile
src/sc2code/libs/input/sdl/Makefile
src/sc2code/libs/sound/Makefile
src/sc2code/libs/sound/sdl/Makefile
src/sc2code/libs/sound/openal/Makefile
src/sc2code/libs/graphics/Makefile
src/sc2code/libs/graphics/sdl/Makefile
src/sc2code/libs/task/Makefile
+21 -9
View File
@@ -42,7 +42,7 @@ RSC=rc.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /MD /W3 /GX /O2 /I ".." /I "..\sc2code" /I "..\sc2code\libs" /I "..\sc2code\ships" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D _VW=320 /D _VH=240 /D "HAVE_OPENGL" /D "GFXMODULE_SDL" /D "SOUNDMODULE_SDL" /YX /FD /c
# ADD CPP /nologo /MD /W3 /GX /O2 /I ".." /I "..\sc2code" /I "..\sc2code\libs" /I "..\sc2code\ships" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D _VW=320 /D _VH=240 /D "HAVE_OPENGL" /D "GFXMODULE_SDL" /D "SOUNDMODULE_OPENAL" /YX /FD /c
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
@@ -50,7 +50,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib SDL.lib SDLmain.lib SDL_image.lib SDL_mixer.lib SDL_sound.lib /nologo /subsystem:console /machine:I386 /nodefaultlib:"msvcrtd.lib" /out:"../../Content/Starcon2.exe"
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib SDL.lib SDLmain.lib SDL_image.lib SDL_sound.lib OpenAL32.lib /nologo /subsystem:console /machine:I386 /nodefaultlib:"msvcrtd.lib" /out:"../../Content/Starcon2.exe"
!ELSEIF "$(CFG)" == "Starcon2 - Win32 Debug"
@@ -66,7 +66,7 @@ LINK32=link.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I ".." /I "..\sc2code" /I "..\sc2code\libs" /I "..\sc2code\ships" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D _VW=320 /D _VH=240 /D "HAVE_OPENGL" /D "GFXMODULE_SDL" /D "SOUNDMODULE_SDL" /FR /YX /FD /GZ /c
# ADD CPP /nologo /MDd /W3 /Gm /GX /ZI /Od /I ".." /I "..\sc2code" /I "..\sc2code\libs" /I "..\sc2code\ships" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" /D _VW=320 /D _VH=240 /D "HAVE_OPENGL" /D "GFXMODULE_SDL" /D "SOUNDMODULE_OPENAL" /FR /YX /FD /GZ /c
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
@@ -74,7 +74,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo /o"Starcon2.bsc"
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib SDL.lib SDLmain.lib SDL_image.lib SDL_mixer.lib SDL_sound.lib /nologo /subsystem:console /debug /machine:I386 /nodefaultlib:"msvcrt.lib" /out:"../../Content/Starcon2Debug.exe" /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib SDL.lib SDLmain.lib SDL_image.lib SDL_sound.lib OpenAL32.lib /nologo /subsystem:console /debug /machine:I386 /nodefaultlib:"msvcrt.lib" /out:"../../Content/Starcon2Debug.exe" /pdbtype:sept
# SUBTRACT LINK32 /nodefaultlib
!ENDIF
@@ -395,24 +395,36 @@ SOURCE=..\sc2code\libs\resource\resintrn.h
# Begin Group "sound"
# PROP Default_Filter ""
# Begin Group "sdl No. 2"
# Begin Group "openal"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\sc2code\libs\sound\sdl\modfuncs.c
SOURCE=..\sc2code\libs\sound\openal\music.c
# End Source File
# Begin Source File
SOURCE=..\sc2code\libs\sound\sdl\play.c
SOURCE=..\sc2code\libs\sound\openal\sfx.c
# End Source File
# Begin Source File
SOURCE=..\sc2code\libs\sound\sdl\sound.c
SOURCE=..\sc2code\libs\sound\openal\sound.c
# End Source File
# Begin Source File
SOURCE=..\sc2code\libs\sound\sdl\trackplayer.c
SOURCE=..\sc2code\libs\sound\openal\sound.h
# End Source File
# Begin Source File
SOURCE=..\sc2code\libs\sound\openal\stream.c
# End Source File
# Begin Source File
SOURCE=..\sc2code\libs\sound\openal\stream.h
# End Source File
# Begin Source File
SOURCE=..\sc2code\libs\sound\openal\trackplayer.c
# End Source File
# End Group
# Begin Source File
+1 -1
View File
@@ -31,7 +31,7 @@ int ScreenHeight;
int ScreenWidthActual;
int ScreenHeightActual;
int GraphicsDriver;
int TFB_DEBUG_HALT;
int TFB_DEBUG_HALT = 0;
int BlendNumerator = 4;
int BlendDenominator = 4;
+1 -1
View File
@@ -45,7 +45,7 @@ enum
int TFB_InitGraphics (int driver, int flags, int width, int height, int bpp);
int TFB_CreateGamePlayThread (void);
void TFB_UninitGraphics ();
void TFB_ProcessEvents (void);
// 3DO Graphics Stuff
@@ -35,7 +35,6 @@ InitGraphics (int argc, char* argv[], COUNT KbytesRequired)
BOOLEAN ret;
LoadDisplay (&_pCurDisplay);
mem_init ();
ActivateDisplay ();
DrawCommandQueue = TFB_DrawCommandQueue_Create ();
@@ -50,7 +49,7 @@ UninitGraphics () // Also probably empty
{
// HFree (DrawCommandQueue); This is static now!
mem_uninit ();
//mem_uninit ();
}
@@ -47,7 +47,6 @@ TFB_GL_InitGraphics (int driver, int flags, int width, int height, int bpp)
SDL_VideoDriverName (VideoName, sizeof (VideoName));
fprintf (stderr, "SDL driver used: %s\n", VideoName);
atexit (SDL_Quit);
fprintf (stderr, "SDL initialized.\n");
fprintf (stderr, "Initializing Screen.\n");
-1
View File
@@ -48,7 +48,6 @@ TFB_Pure_InitGraphics (int driver, int flags, int width, int height, int bpp)
// For Linux: x11 (default), dga, fbcon, directfb, svgalib,
// ggi, aalib
// For Windows: directx (default), windib
atexit (SDL_Quit);
fprintf (stderr, "SDL initialized.\n");
+5 -10
View File
@@ -50,6 +50,8 @@ TFB_InitGraphics (int driver, int flags, int width, int height, int bpp)
exit(-1);
}
atexit (TFB_UninitGraphics);
if (driver == TFB_GFXDRIVER_SDL_OPENGL)
{
#ifdef HAVE_OPENGL
@@ -77,17 +79,10 @@ TFB_InitGraphics (int driver, int flags, int width, int height, int bpp)
return 0;
}
int
TFB_CreateGamePlayThread ()
void
TFB_UninitGraphics (void)
{
TFB_DEBUG_HALT = 0;
GraphicsSem = SDL_CreateSemaphore (1);
_MemorySem = SDL_CreateSemaphore (1);
SDL_CreateThread (Starcon2Main, NULL);
return 0;
SDL_Quit ();
}
void
@@ -29,5 +29,6 @@ enum
//#define TFB_INPUTFLAGS_ETC (1<<0)
int TFB_InitInput (int driver, int flags);
void TFB_UninitInput (void);
#endif
+8
View File
@@ -19,6 +19,7 @@
#ifdef GFXMODULE_SDL
#include "libs/graphics/sdl/sdl_common.h"
#include "libs/input/input_common.h"
Uint8 KeyboardDown[512];
@@ -48,6 +49,8 @@ TFB_InitInput (int driver, int flags)
int i;
SDL_Joystick *Joystick1;
atexit (TFB_UninitInput);
if ((SDL_InitSubSystem(SDL_INIT_JOYSTICK)) == -1)
{
fprintf (stderr, "Couldn't initialize joystick subsystem: %s\n", SDL_GetError());
@@ -86,6 +89,11 @@ TFB_InitInput (int driver, int flags)
return 0;
}
void
TFB_UninitInput (void)
{
}
void
ProcessKeyboardEvent(const SDL_Event *Event)
{
+2 -2
View File
@@ -3,7 +3,7 @@
# Written by Mudry <mudry@user.sf.net>, protected by GNU GPL.
# CVS $ Id: $
SUBDIRS = sdl
SUBDIRS = openal
INCLUDES = @SDL_CFLAGS@ \
-I$(top_srcdir)/src \
@@ -12,6 +12,6 @@ INCLUDES = @SDL_CFLAGS@ \
noinst_LTLIBRARIES = libsound.la
libsound_la_SOURCES = fileinst.c resinst.c sound_common.c
libsound_la_LIBADD = sdl/libsdlsound.la
libsound_la_LIBADD = openal/libopenalsound.la
noinst_HEADERS = play.h redbook.h sndintrn.h trackplayer.h sound_common.h
@@ -0,0 +1,15 @@
# Automake template file.
# Written by Mudry <mudry@user.sf.net>, protected by GNU GPL.
# CVS $ Id: $
INCLUDES = @SDL_CFLAGS@ \
-I$(top_srcdir)/src \
-I$(top_srcdir)/src/sc2code \
-I$(top_srcdir)/src/sc2code/libs
noinst_LTLIBRARIES = libopenalsound.la
libopenalsound_la_SOURCES = music.c sfx.c sound.c stream.c trackplayer.c
noinst_HEADERS = sound.h stream.h
+187
View File
@@ -0,0 +1,187 @@
/*
* 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"
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);
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
{
*pmus = (TFB_SoundSample *) HMalloc (sizeof (TFB_SoundSample));
if (((*pmus)->decoder = Sound_NewSampleFromFile (_cur_resfile_name, NULL, 4096)) == 0)
{
fprintf (stderr, "_GetMusicData(): couldn't load %s\n", _cur_resfile_name);
UnlockMusicData (h);
mem_release (h);
h = 0;
HFree (*pmus);
}
else
{
fprintf (stderr, "decoder %s rate %d channels %d\n", (*pmus)->decoder->decoder->description,
(*pmus)->decoder->actual.rate, (*pmus)->decoder->actual.channels);
alGenBuffers (NUM_SOUNDBUFFERS, (*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)
{
LockMutex (soundSource[MUSIC_SOURCE].stream_mutex);
if (soundSource[MUSIC_SOURCE].sample == (*pmus))
{
StopStream (MUSIC_SOURCE);
}
UnlockMutex (soundSource[MUSIC_SOURCE].stream_mutex);
Sound_FreeSample ((*pmus)->decoder);
alDeleteBuffers (NUM_SOUNDBUFFERS, (*pmus)->buffer);
}
HFree (*pmus);
UnlockMusicData (handle);
mem_release (handle);
return (TRUE);
}
#endif
+258
View File
@@ -0,0 +1,258 @@
/*
* 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;
//fprintf (stderr, "PlayChannel %d tfb_sample %x\n", channel, tfb_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]->decoder = Sound_NewSampleFromFile (filename, NULL, 4096);
if (!sndfx[snd_ct]->decoder)
{
fprintf (stderr, "_GetSoundBankData(): couldn't load %s\n", filename);
HFree (sndfx[snd_ct]);
}
else
{
Uint32 decoded_bytes;
ALenum format;
decoded_bytes = Sound_DecodeAll (sndfx[snd_ct]->decoder);
//fprintf (stderr, "decoded_bytes %d\n", decoded_bytes);
format = DetermineALFormat (sndfx[snd_ct]->decoder);
alGenBuffers (NUM_SOUNDBUFFERS, sndfx[snd_ct]->buffer);
alBufferData (sndfx[snd_ct]->buffer[0], format,
sndfx[snd_ct]->decoder->buffer, decoded_bytes,
sndfx[snd_ct]->decoder->actual.rate);
Sound_FreeSample (sndfx[snd_ct]->decoder);
sndfx[snd_ct]->decoder = NULL;
++snd_ct;
}
}
else
{
fprintf (stderr, "_GetSoundBankData: Bad file!\n");
}
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)
Sound_FreeSample (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--)
{
Sound_FreeSample ((*sptr)->decoder);
alDeleteBuffers (NUM_SOUNDBUFFERS, (*sptr)->buffer);
HFree (*sptr);
*sptr++ = 0;
}
UnlockStringTable (Snd);
FreeStringTable (Snd);
return (TRUE);
}
return (FALSE);
}
BOOLEAN
DestroySound(SOUND_REF target)
{
return (_ReleaseSoundBankData (target));
}
#endif
+238
View File
@@ -0,0 +1,238 @@
/*
* 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"
ALCcontext *alcContext = NULL;
ALCdevice *alcDevice = NULL;
ALfloat listenerPos[] = {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};
TFB_SoundSource soundSource[NUM_SOUNDSOURCES];
static Task StreamDecoderTask;
int
TFB_InitSound (int driver, int flags, int frequency)
{
int i;
fprintf (stderr, "Initializing OpenAL.\n");
atexit (TFB_UninitSound);
#ifdef WIN32
alcDevice = alcOpenDevice ((ALubyte*)"DirectSound3D");
#else
alcDevice = alcOpenDevice (NULL);
#endif
if (!alcDevice)
{
fprintf (stderr,"Couldn't initialize OpenAL: %d\n", alcGetError (NULL));
exit (-1);
}
alcContext = alcCreateContext (alcDevice, NULL);
if (!alcContext)
{
fprintf (stderr, "Couldn't create OpenAL context: %d\n", alcGetError (alcDevice));
}
alcMakeContextCurrent (alcContext);
fprintf (stderr, "OpenAL initialized.\n");
fprintf (stderr, " version: %s\n", alGetString (AL_VERSION));
fprintf (stderr, " vendor: %s\n", alGetString (AL_VENDOR));
fprintf (stderr, " renderer: %s\n", alGetString (AL_RENDERER));
fprintf (stderr, " device: %s\n",
alcGetString (alcDevice, ALC_DEFAULT_DEVICE_SPECIFIER));
fprintf (stderr, "Initializing SDL_sound.\n");
if (!Sound_Init())
{
fprintf(stderr, "SDL_sound initialization failed: %s\n", Sound_GetError());
exit (-1);
}
else
{
const Sound_DecoderInfo **sdi;
Sound_Version compiled, linked;
SOUND_VERSION (&compiled);
Sound_GetLinkedVersion (&linked);
fprintf (stderr, "SDL_sound initialized.\n");
fprintf (stderr, " compiled version: %d.%d.%d linked version: %d.%d.%d\n",
compiled.major, compiled.minor, compiled.patch,
linked.major, linked.minor, linked.patch);
for (sdi = Sound_AvailableDecoders(); *sdi != NULL; ++sdi)
{
fprintf (stderr, " supported format: %s\n",
(*sdi)->description);
}
}
alListenerfv (AL_POSITION, listenerPos);
alListenerfv (AL_VELOCITY, listenerVel);
alListenerfv (AL_ORIENTATION, listenerOri);
for (i = 0; i < NUM_SOUNDSOURCES; ++i)
{
float zero[3] = {0.0f, 0.0f, 0.0f};
alGenSources (1, &soundSource[i].handle);
alSourcei (soundSource[i].handle, AL_LOOPING, AL_FALSE);
alSourcefv (soundSource[i].handle, AL_POSITION, zero);
alSourcefv (soundSource[i].handle, AL_VELOCITY, zero);
alSourcefv (soundSource[i].handle, AL_DIRECTION, zero);
soundSource[i].sample = NULL;
soundSource[i].stream_looping = FALSE;
soundSource[i].stream_should_be_playing = FALSE;
soundSource[i].stream_mutex = CreateMutex ();
}
SetSFXVolume (sfxVolumeScale);
SetSpeechVolume (speechVolumeScale);
SetMusicVolume (musicVolume);
// NOTE: change this if implementing 3D sound stuff
alDistanceModel (AL_NONE);
StreamDecoderTask = AssignTask (StreamDecoderTaskFunc, 1024,
"audio stream decoder");
return 0;
}
void
TFB_UninitSound (void)
{
ConcludeTask (StreamDecoderTask);
alcMakeContextCurrent (NULL);
alcDestroyContext (alcContext);
alcContext = NULL;
alcCloseDevice (alcDevice);
alcDevice = NULL;
}
void
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)
{
if (soundSource[i].sample && soundSource[i].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;
}
// Status: Ignored
BOOLEAN
InitSound (int argc, char* argv[])
{
return TRUE;
}
// Status: Ignored
void
UninitSound (void)
{
}
ALenum
DetermineALFormat (Sound_Sample *sample)
{
ALenum format;
if (sample->actual.channels == 1)
{
if (sample->actual.format == AUDIO_U8 ||
sample->actual.format == AUDIO_S8)
{
format = AL_FORMAT_MONO8;
}
else
{
format = AL_FORMAT_MONO16;
}
}
else
{
if (sample->actual.format == AUDIO_U8 ||
sample->actual.format == AUDIO_S8)
{
format = AL_FORMAT_STEREO8;
}
else
{
format = AL_FORMAT_STEREO16;
}
}
return format;
}
void SetSFXVolume (float volume)
{
int i;
for (i = FIRST_SFX_SOURCE; i <= LAST_SFX_SOURCE; ++i)
{
alSourcef (soundSource[i].handle, AL_GAIN, sfxVolumeScale);
}
}
void SetSpeechVolume (float volume)
{
alSourcef (soundSource[SPEECH_SOURCE].handle, AL_GAIN, speechVolumeScale);
}
#endif
+72
View File
@@ -0,0 +1,72 @@
/*
* 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 "libs/strings/strintrn.h"
#include "libs/sound/sndintrn.h"
#include "libs/graphics/sdl/sdl_common.h"
#include "libs/sound/sound_common.h"
#ifdef WIN32
#include <al.h>
#include <alc.h>
#include <SDL_sound.h>
#else
#include <AL/al.h>
#include <AL/alc.h>
#include <SDL/SDL_sound.h>
#endif
#define NUM_SOUNDBUFFERS 8
#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)
// audio data
typedef struct tfb_soundsample
{
Sound_Sample *decoder; // if != NULL, sound is streamed
ALuint buffer[NUM_SOUNDBUFFERS]; // if not streamed, only buffer[0] is used
} TFB_SoundSample;
// equivalent to channel in legacy sound code
typedef struct tfb_soundsource
{
TFB_SoundSample *sample;
ALuint handle;
BOOLEAN stream_looping;
BOOLEAN stream_should_be_playing;
Mutex stream_mutex;
} 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[];
ALenum DetermineALFormat (Sound_Sample *sample);
void SetSFXVolume (float volume);
void SetSpeechVolume (float volume);
#include "stream.h"
+238
View File
@@ -0,0 +1,238 @@
/*
* 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 "sound.h"
BOOLEAN speech_callback = FALSE;
void
PlayStream (TFB_SoundSample *sample, ALuint source, BOOLEAN looping)
{
int i;
ALenum format = DetermineALFormat (sample->decoder);
StopStream (source);
Sound_Rewind (sample->decoder);
soundSource[source].sample = sample;
alSourcei (soundSource[source].handle, AL_LOOPING, AL_FALSE);
for (i = 0; i < NUM_SOUNDBUFFERS; ++i)
{
Uint32 decoded_bytes;
if (sample->decoder->flags & SOUND_SAMPLEFLAG_EOF ||
sample->decoder->flags & SOUND_SAMPLEFLAG_ERROR)
break;
decoded_bytes = Sound_Decode (sample->decoder);
//fprintf (stderr, "PlayStream(): source %d sample %x decoded_bytes %d\n", source, sample, decoded_bytes);
if (decoded_bytes == 0)
break;
alBufferData (sample->buffer[i], format, sample->decoder->buffer,
decoded_bytes, sample->decoder->actual.rate);
alSourceQueueBuffers (soundSource[source].handle, 1, &sample->buffer[i]);
}
soundSource[source].stream_looping = looping;
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;
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_SOUNDBUFFERS %d\n",
// source, processed, queued, NUM_SOUNDBUFFERS);
buffer = (ALuint *) HMalloc (sizeof (ALuint) * processed);
alSourceUnqueueBuffers (soundSource[source].handle, processed, buffer);
HFree (buffer);
}
void
PauseStream (ALuint source)
{
soundSource[source].stream_should_be_playing = FALSE;
alSourcePause (soundSource[source].handle);
}
void
ResumeStream (ALuint source)
{
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;
while (!Task_ReadState (task, TASK_EXIT))
{
int i;
SleepThread (1);
for (i = MUSIC_SOURCE; i < NUM_SOUNDSOURCES; ++i)
{
ALuint processed;
//ALuint queued;
ALint state;
ALboolean finished = 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->flags & SOUND_SAMPLEFLAG_EOF ||
soundSource[i].sample->decoder->flags & SOUND_SAMPLEFLAG_ERROR)
{
UnlockMutex (soundSource[i].stream_mutex);
continue;
}
alGetSourcei (soundSource[i].handle, AL_BUFFERS_PROCESSED, &processed);
if (processed == 0)
{
alGetSourcei (soundSource[i].handle, AL_SOURCE_STATE, &state);
if (state != AL_PLAYING)
{
//fprintf (stderr, "StreamDecoderTaskFunc(): forcing alSourcePlay on %d\n", i);
alSourcePlay (soundSource[i].handle);
}
}
//alGetSourcei (soundSource[i].handle, AL_BUFFERS_QUEUED, &queued);
//fprintf (stderr, "StreamDecoderTaskFunc(): source %d, processed %d queued %d\n", i, processed, queued);
while (processed && !finished)
{
ALenum format, error;
ALuint buffer;
Uint32 decoded_bytes;
alGetError (); // clear error state
alSourceUnqueueBuffers (soundSource[i].handle, 1, &buffer);
if ((error = alGetError()) != AL_NO_ERROR)
{
fprintf (stderr, "StreamDecoderTaskFunc(): OpenAL error after alSourceUnqueueBuffers: %x, source %d\n", error, i);
break;
}
decoded_bytes = Sound_Decode (soundSource[i].sample->decoder);
if (soundSource[i].sample->decoder->flags & SOUND_SAMPLEFLAG_EOF)
{
if (i == SPEECH_SOURCE && speech_callback)
{
advance_track (0);
finished = AL_TRUE;
soundSource[i].stream_should_be_playing = FALSE;
}
else
{
if (soundSource[i].stream_looping)
{
if ((Sound_Rewind (soundSource[i].sample->decoder)) == 0)
{
fprintf (stderr, "StreamDecoderTaskFunc(): Sound_Rewind error %s, source %d\n",
Sound_GetError(), i);
finished = AL_TRUE;
soundSource[i].stream_should_be_playing = FALSE;
}
else if (decoded_bytes == 0)
{
decoded_bytes = Sound_Decode (soundSource[i].sample->decoder);
}
}
else
{
finished = AL_TRUE;
soundSource[i].stream_should_be_playing = FALSE;
}
}
}
else if (soundSource[i].sample->decoder->flags & SOUND_SAMPLEFLAG_ERROR)
{
fprintf (stderr, "StreamDecoderTaskFunc(): Sound_Decode error %s, source %d\n",
Sound_GetError(), i);
soundSource[i].stream_should_be_playing = FALSE;
break;
}
if (decoded_bytes > 0)
{
format = DetermineALFormat (soundSource[i].sample->decoder);
alBufferData (buffer, format, soundSource[i].sample->decoder->buffer,
decoded_bytes, soundSource[i].sample->decoder->actual.rate);
if ((error = alGetError()) != AL_NO_ERROR)
{
fprintf (stderr, "StreamDecoderTaskFunc(): OpenAL error after alBufferData: %x, source %d, decoded_bytes %d\n", error, i, decoded_bytes);
finished = AL_TRUE;
}
else
{
alSourceQueueBuffers (soundSource[i].handle, 1, &buffer);
if ((error = alGetError()) != AL_NO_ERROR)
{
fprintf (stderr, "StreamDecoderTaskFunc(): OpenAL error after alSourceQueueBuffers: %x, source %d, decoded_bytes %d\n", error, i, decoded_bytes);
finished = AL_TRUE;
}
}
}
processed--;
}
UnlockMutex (soundSource[i].stream_mutex);
}
}
FinishTask (task);
return 0;
}
#endif
@@ -0,0 +1,33 @@
/*
* 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
*/
#ifndef STREAM_H
#define STREAM_H
void PlayStream (TFB_SoundSample *sample, ALuint source, BOOLEAN looping);
void StopStream (ALuint source);
void PauseStream (ALuint source);
void ResumeStream (ALuint source);
BOOLEAN PlayingStream (ALuint source);
int StreamDecoderTaskFunc (void *data);
extern BOOLEAN speech_callback;
void advance_track (int channel_finished);
#endif
@@ -0,0 +1,266 @@
/*
* 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 "libs/sound/trackplayer.h"
extern int do_subtitles (UNICODE *pStr);
static int tct, tcur, no_voice;
#define MAX_CLIPS 50
static struct
{
int text_spliced;
UNICODE *text;
TFB_SoundSample *sample;
} track_clip[MAX_CLIPS];
void
JumpTrack (int abort)
{
speech_callback = FALSE;
if (track_clip[tcur].sample)
{
LockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
StopStream (SPEECH_SOURCE);
UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
}
no_voice = 1;
do_subtitles ((void *)~0);
if (abort)
tcur = tct;
}
void
advance_track (int channel_finished)
{
if (channel_finished <= 0)
{
if (channel_finished == 0)
++tcur;
if (tcur < tct)
{
LockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
PlayStream (track_clip[tcur].sample, SPEECH_SOURCE, FALSE);
UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
do_subtitles (0);
}
else if (channel_finished == 0)
{
--tcur;
no_voice = 1;
}
}
}
void
ResumeTrack ()
{
if (tcur < tct)
{
ALint state;
LockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
alGetSourcei (soundSource[SPEECH_SOURCE].handle, AL_SOURCE_STATE, &state);
UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
if (!soundSource[SPEECH_SOURCE].stream_should_be_playing &&
state == AL_PAUSED)
{
LockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
ResumeStream (SPEECH_SOURCE);
UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
}
else if (!no_voice)
{
if (tcur == 0)
{
speech_callback = TRUE;
}
advance_track (-1);
}
}
}
COUNT
PlayingTrack ()
{
if (tcur < tct)
{
if (do_subtitles (track_clip[tcur].text) ||
(no_voice && ++tcur < tct && do_subtitles (0)))
{
return (tcur + 1);
}
else if (track_clip[tcur].sample)
{
COUNT result;
LockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
result = (PlayingStream (SPEECH_SOURCE) ? (COUNT)(tcur + 1) : 0);
UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
return result;
}
}
return (0);
}
void
StopTrack ()
{
speech_callback = FALSE;
LockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
StopStream (SPEECH_SOURCE);
UnlockMutex (soundSource[SPEECH_SOURCE].stream_mutex);
while (tct--)
{
if (track_clip[tct].text_spliced)
{
track_clip[tct].text_spliced = 0;
HFree (track_clip[tct].text);
track_clip[tct].text = 0;
}
if (track_clip[tct].sample)
{
if (track_clip[tct].sample->decoder)
{
Sound_FreeSample (track_clip[tct].sample->decoder);
alDeleteBuffers (NUM_SOUNDBUFFERS, track_clip[tct].sample->buffer);
}
HFree (track_clip[tct].sample);
track_clip[tct].sample = 0;
}
}
tct = tcur = 0;
no_voice = 0;
do_subtitles (0);
}
void
SpliceTrack (UNICODE *TrackName, UNICODE *TrackText)
{
if (TrackText)
{
if (TrackName == 0)
{
if (tct)
{
int slen1, slen2;
UNICODE *oTT;
oTT = track_clip[tct - 1].text;
slen1 = wstrlen (oTT);
slen2 = wstrlen (TrackText);
if (track_clip[tct - 1].text_spliced)
track_clip[tct - 1].text = HRealloc (oTT, slen1 + slen2 + 1);
else
{
track_clip[tct - 1].text = HMalloc (slen1 + slen2 + 1);
wstrcpy (track_clip[tct - 1].text, oTT);
track_clip[tct - 1].text_spliced = 1;
}
wstrcpy (&track_clip[tct - 1].text[slen1], TrackText);
}
}
else if (tct < MAX_CLIPS)
{
track_clip[tct].text = TrackText;
track_clip[tct].text_spliced = 0;
fprintf (stderr, "SpliceTrack(): loading %s\n", TrackName);
track_clip[tct].sample = (TFB_SoundSample *) HMalloc (sizeof (TFB_SoundSample));
track_clip[tct].sample->decoder = Sound_NewSampleFromFile (TrackName, NULL, 4096);
if (track_clip[tct].sample->decoder)
{
fprintf (stderr, "decoder %s rate %d channels %d\n",
track_clip[tct].sample->decoder->decoder->description,
track_clip[tct].sample->decoder->actual.rate,
track_clip[tct].sample->decoder->actual.channels);
alGenBuffers (NUM_SOUNDBUFFERS, track_clip[tct].sample->buffer);
}
else
{
fprintf (stderr, "SpliceTrack(): couldn't load %s: %s\n",
TrackName, Sound_GetError());
HFree (track_clip[tct].sample);
track_clip[tct].sample = NULL;
}
++tct;
}
}
}
void
PauseTrack ()
{
/*if (tcur < tct && track_clip[tcur].chunk)
Mix_Pause (VOICE_CHANNEL);*/
}
void
FastReverse ()
{
JumpTrack (0);
no_voice = 0;
tcur = 0;
ResumeTrack ();
}
void
FastForward ()
{
JumpTrack (0);
//no_voice = 0;
}
int
GetSoundData (char* data)
// Returns the data size. Only used in oscill.c
{
//fprintf (stderr, "Unimplemented function activated: GetSoundData()\n");
return 0;
}
// Status: Unimplemented
int
GetSoundInfo (int *length, int *offset)
// Umm... How does it know which sound?
// Answer: only used in oscill.c slider so sound must be current speech
{
//fprintf (stderr, "Unimplemented function activated: GetSoundInfo()\n");
*length = 1;
*offset = 0;
return 1;
}
#endif
+27 -18
View File
@@ -26,47 +26,56 @@
int
TFB_InitSound (int driver, int flags, int frequency)
{
// NOTE: SDL_sound should be compiled without mikmod support
// or potential lockup occurs because both
// SDL_mixer and SDL_sound try to initialize it
char SoundcardName[256];
int audio_rate,audio_channels;
Uint16 audio_format;
SDL_version compile_version;
fprintf (stderr, "Initializing SDL audio subsystem.\n");
if ((SDL_InitSubSystem(SDL_INIT_AUDIO)) == -1)
{
fprintf (stderr, "Couldn't initialize audio subsystem: %s\n", SDL_GetError());
exit(-1);
}
fprintf (stderr, "SDL audio subsystem initialized.\n");
fprintf (stderr, "Initializing SDL_mixer.\n");
if (Mix_OpenAudio(frequency, AUDIO_S16, 2, 2048))
{
fprintf (stderr, "Unable to open audio: %s\n", Mix_GetError());
exit (-1);
}
fprintf (stderr, "SDL_mixer initialized.\n");
atexit (Mix_CloseAudio);
SDL_AudioDriverName (SoundcardName, sizeof (SoundcardName));
Mix_QuerySpec (&audio_rate, &audio_format, &audio_channels);
fprintf (stderr, " opened %s at %d Hz %d bit %s, %d bytes audio buffer\n",
SoundcardName, audio_rate, audio_format & 0xFF,
audio_channels > 1 ? "stereo" : "mono", 2048);
MIX_VERSION (&compile_version);
fprintf (stderr, " compiled with SDL_mixer version: %d.%d.%d\n",
compile_version.major,
compile_version.minor,
compile_version.patch);
fprintf (stderr, " running with SDL_mixer version: %d.%d.%d\n",
Mix_Linked_Version()->major,
Mix_Linked_Version()->minor,
Mix_Linked_Version()->patch);
fprintf (stderr, "Initializing SDL_sound.\n");
fprintf (stderr, "(NOTE: if this locks up, compile SDL_sound without libmikmod support)\n");
fflush (stderr);
if (!Sound_Init())
{
fprintf(stderr, "Sound_Init() failed: %s\n", Sound_GetError());
exit (-1);
}
SDL_AudioDriverName (SoundcardName, sizeof (SoundcardName));
Mix_QuerySpec (&audio_rate, &audio_format, &audio_channels);
fprintf (stderr, "Opened %s at %d Hz %d bit %s, %d bytes audio buffer\n",
SoundcardName, audio_rate, audio_format & 0xFF,
audio_channels > 1 ? "stereo" : "mono", 2048);
MIX_VERSION (&compile_version);
fprintf (stderr, "Compiled with SDL_mixer version: %d.%d.%d\n",
compile_version.major,
compile_version.minor,
compile_version.patch);
fprintf (stderr, "Running with SDL_mixer version: %d.%d.%d\n",
Mix_Linked_Version()->major,
Mix_Linked_Version()->minor,
Mix_Linked_Version()->patch);
fprintf (stderr, "SDL_sound initialized.\n");
return 0;
}
+6 -3
View File
@@ -20,7 +20,10 @@
#include "libs/sound/sound_common.h"
#include "libs/tasklib.h"
extern int _music_volume;
int musicVolume = (MAX_VOLUME >> 1);
float musicVolumeScale = 1.0f;
float sfxVolumeScale = 1.0f;
float speechVolumeScale = 1.0f;
static Task FadeTask;
static SIZE TTotal;
@@ -33,7 +36,7 @@ fade_task (void *data)
DWORD StartTime, CurTime;
Task task = (Task) data;
volume_beg = _music_volume;
volume_beg = musicVolume;
StartTime = CurTime = GetTimeCounter ();
do
{
@@ -58,7 +61,7 @@ FadeMusic (BYTE end_vol, SIZE TimeInterval)
if (FadeTask)
{
volume_end = _music_volume;
volume_end = musicVolume;
TTotal = 1;
do
TaskSwitch ();
@@ -29,5 +29,11 @@ enum
//#define TFB_SOUNDFLAGS_ETC (1<<0)
int TFB_InitSound (int driver, int flags, int frequency);
void TFB_UninitSound (void);
extern int musicVolume;
extern float musicVolumeScale;
extern float sfxVolumeScale;
extern float speechVolumeScale;
#endif
+40 -4
View File
@@ -61,6 +61,7 @@ main (int argc, char *argv[])
int gfxflags = 0;
int width = 640, height = 480, bpp = 16;
int frequency = 44100;
int vol;
char contentdir[1000];
int option_index = 0, c;
@@ -76,6 +77,9 @@ main (int argc, char *argv[])
{"tv", 0, NULL, 't'},
{"contentdir", 1, NULL, 'c'},
{"help", 0, NULL, 'h'},
{"musicvol", 1, NULL, 'M'},
{"sfxvol", 1, NULL, 'S'},
{"speechvol", 1, NULL, 'T'},
{0, 0, 0, 0}
};
@@ -85,7 +89,7 @@ main (int argc, char *argv[])
strcpy (contentdir, "../../content");
#endif
while ((c = getopt_long(argc, argv, "r:d:fobq:ptc:?h", long_options, &option_index)) != -1)
while ((c = getopt_long(argc, argv, "r:d:fobq:ptc:?hM:S:T:", long_options, &option_index)) != -1)
{
switch (c) {
case 'r':
@@ -115,6 +119,30 @@ main (int argc, char *argv[])
case 'c':
sscanf(optarg, "%s", contentdir);
break;
case 'M':
sscanf(optarg, "%d", &vol);
if (vol < 0)
vol = 0;
if (vol > 100)
vol = 100;
musicVolumeScale = vol / 100.0f;
break;
case 'S':
sscanf(optarg, "%d", &vol);
if (vol < 0)
vol = 0;
if (vol > 100)
vol = 100;
sfxVolumeScale = vol / 100.0f;
break;
case 'T':
sscanf(optarg, "%d", &vol);
if (vol < 0)
vol = 0;
if (vol > 100)
vol = 100;
speechVolumeScale = vol / 100.0f;
break;
default:
printf ("\nOption %s not found!\n", long_options[option_index].name);
case '?':
@@ -122,7 +150,7 @@ main (int argc, char *argv[])
printf("\nThe Ur-Quan Masters\n");
printf("Options:\n");
printf(" -r, --res=WIDTHxHEIGHT\n");
printf(" -d, --bpp=BITSPERPLANE\n");
printf(" -d, --bpp=BITSPERPIXEL\n");
printf(" -f, --fullscreen\n");
printf(" -o, --opengl\n");
printf(" -b, --bilinear\n");
@@ -130,6 +158,9 @@ main (int argc, char *argv[])
printf(" -p, --fps\n");
printf(" -t, --tv\n");
printf(" -c, --contentdir=CONTENTDIR\n");
printf(" -M, --musicvol=VOLUME (0-100)\n");
printf(" -S, --sfxvol=VOLUME (0-100)\n");
printf(" -T, --speechvol=VOLUME (0-100)\n");
return 0;
break;
}
@@ -140,11 +171,16 @@ main (int argc, char *argv[])
InitThreadSystem ();
InitTimeSystem ();
InitTaskSystem ();
_MemorySem = CreateSemaphore (1);
GraphicsSem = CreateSemaphore (1);
mem_init ();
TFB_InitGraphics (gfxdriver, gfxflags, width, height, bpp);
TFB_InitSound (TFB_SOUNDDRIVER_SDL, 0, frequency);
TFB_InitInput (TFB_INPUTDRIVER_SDL, 0);
TFB_CreateGamePlayThread ();
AssignTask (Starcon2Main, 1024, "Starcon2Main");
for (;;)
{
@@ -152,5 +188,5 @@ main (int argc, char *argv[])
TFB_FlushGraphics ();
}
return 0;
exit(0);
}