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/ Homepage: http://www.libsdl.org/projects/SDL_image/
Download: http://www.libsdl.org/projects/SDL_image/release/ 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 SDL-sound
A sound loader library used with SDL. An audio format decoder library.
Homepage: http://www.icculus.org/SDL_sound/ Homepage: http://www.icculus.org/SDL_sound/
Download: http://www.icculus.org/SDL_sound/downloads/ 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 If you find these aren't enough, or if you know the names
of the corresponding RPM etc. packages, please report to 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 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 complete battle (not just one fight). There's no permanent memory leak
though. 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): Implementation bugs (low priority):
- The main thread is still created by a direct all to the SDL function, - 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 which we can free when no more memory is available, to allow an emergency
save. save.
- How about an ISO image for a self-contained linux CD which boots into SC2? - 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 # Configurables
CFLAGS="$CFLAGS -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_SDL" CPPFLAGS="$CPPFLAGS -g -W -Wall -DHAVE_OPENGL -DSDL_PTHREADS -DGFXMODULE_SDL -DSOUNDMODULE_OPENAL"
# -------------------------------------------------------------------------- # --------------------------------------------------------------------------
@@ -68,11 +68,11 @@ AC_CHECK_FUNCS([strupr])
# Check for SDL # Check for SDL
SDL_VERSION=1.2.2 SDL_VERSION=1.2.2
AM_PATH_SDL($SDL_VERSION, , AC_MSG_ERROR([*** SDL version $SDL_VERSION not found!])) 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_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(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_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) # Select platform dependent OpenGL libs.. (tweak your platform here)
case "$target" in case "$target" in
@@ -211,7 +211,7 @@ AC_CONFIG_FILES([
src/sc2code/libs/input/Makefile src/sc2code/libs/input/Makefile
src/sc2code/libs/input/sdl/Makefile src/sc2code/libs/input/sdl/Makefile
src/sc2code/libs/sound/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/Makefile
src/sc2code/libs/graphics/sdl/Makefile src/sc2code/libs/graphics/sdl/Makefile
src/sc2code/libs/task/Makefile src/sc2code/libs/task/Makefile
+21 -9
View File
@@ -42,7 +42,7 @@ RSC=rc.exe
# PROP Ignore_Export_Lib 0 # PROP Ignore_Export_Lib 0
# PROP Target_Dir "" # PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c # 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 BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG" # ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe BSC32=bscmake.exe
@@ -50,7 +50,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo # ADD BSC32 /nologo
LINK32=link.exe 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 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" !ELSEIF "$(CFG)" == "Starcon2 - Win32 Debug"
@@ -66,7 +66,7 @@ LINK32=link.exe
# PROP Ignore_Export_Lib 0 # PROP Ignore_Export_Lib 0
# PROP Target_Dir "" # 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 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 BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe BSC32=bscmake.exe
@@ -74,7 +74,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo /o"Starcon2.bsc" # ADD BSC32 /nologo /o"Starcon2.bsc"
LINK32=link.exe 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 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 # SUBTRACT LINK32 /nodefaultlib
!ENDIF !ENDIF
@@ -395,24 +395,36 @@ SOURCE=..\sc2code\libs\resource\resintrn.h
# Begin Group "sound" # Begin Group "sound"
# PROP Default_Filter "" # PROP Default_Filter ""
# Begin Group "sdl No. 2" # Begin Group "openal"
# PROP Default_Filter "" # PROP Default_Filter ""
# Begin Source File # Begin Source File
SOURCE=..\sc2code\libs\sound\sdl\modfuncs.c SOURCE=..\sc2code\libs\sound\openal\music.c
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\sc2code\libs\sound\sdl\play.c SOURCE=..\sc2code\libs\sound\openal\sfx.c
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\sc2code\libs\sound\sdl\sound.c SOURCE=..\sc2code\libs\sound\openal\sound.c
# End Source File # End Source File
# Begin 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 Source File
# End Group # End Group
# Begin Source File # Begin Source File
+1 -1
View File
@@ -31,7 +31,7 @@ int ScreenHeight;
int ScreenWidthActual; int ScreenWidthActual;
int ScreenHeightActual; int ScreenHeightActual;
int GraphicsDriver; int GraphicsDriver;
int TFB_DEBUG_HALT; int TFB_DEBUG_HALT = 0;
int BlendNumerator = 4; int BlendNumerator = 4;
int BlendDenominator = 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_InitGraphics (int driver, int flags, int width, int height, int bpp);
int TFB_CreateGamePlayThread (void); void TFB_UninitGraphics ();
void TFB_ProcessEvents (void); void TFB_ProcessEvents (void);
// 3DO Graphics Stuff // 3DO Graphics Stuff
@@ -35,7 +35,6 @@ InitGraphics (int argc, char* argv[], COUNT KbytesRequired)
BOOLEAN ret; BOOLEAN ret;
LoadDisplay (&_pCurDisplay); LoadDisplay (&_pCurDisplay);
mem_init ();
ActivateDisplay (); ActivateDisplay ();
DrawCommandQueue = TFB_DrawCommandQueue_Create (); DrawCommandQueue = TFB_DrawCommandQueue_Create ();
@@ -50,7 +49,7 @@ UninitGraphics () // Also probably empty
{ {
// HFree (DrawCommandQueue); This is static now! // 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)); SDL_VideoDriverName (VideoName, sizeof (VideoName));
fprintf (stderr, "SDL driver used: %s\n", VideoName); fprintf (stderr, "SDL driver used: %s\n", VideoName);
atexit (SDL_Quit);
fprintf (stderr, "SDL initialized.\n"); fprintf (stderr, "SDL initialized.\n");
fprintf (stderr, "Initializing Screen.\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, // For Linux: x11 (default), dga, fbcon, directfb, svgalib,
// ggi, aalib // ggi, aalib
// For Windows: directx (default), windib // For Windows: directx (default), windib
atexit (SDL_Quit);
fprintf (stderr, "SDL initialized.\n"); 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); exit(-1);
} }
atexit (TFB_UninitGraphics);
if (driver == TFB_GFXDRIVER_SDL_OPENGL) if (driver == TFB_GFXDRIVER_SDL_OPENGL)
{ {
#ifdef HAVE_OPENGL #ifdef HAVE_OPENGL
@@ -77,17 +79,10 @@ TFB_InitGraphics (int driver, int flags, int width, int height, int bpp)
return 0; return 0;
} }
int void
TFB_CreateGamePlayThread () TFB_UninitGraphics (void)
{ {
TFB_DEBUG_HALT = 0; SDL_Quit ();
GraphicsSem = SDL_CreateSemaphore (1);
_MemorySem = SDL_CreateSemaphore (1);
SDL_CreateThread (Starcon2Main, NULL);
return 0;
} }
void void
@@ -29,5 +29,6 @@ enum
//#define TFB_INPUTFLAGS_ETC (1<<0) //#define TFB_INPUTFLAGS_ETC (1<<0)
int TFB_InitInput (int driver, int flags); int TFB_InitInput (int driver, int flags);
void TFB_UninitInput (void);
#endif #endif
+8
View File
@@ -19,6 +19,7 @@
#ifdef GFXMODULE_SDL #ifdef GFXMODULE_SDL
#include "libs/graphics/sdl/sdl_common.h" #include "libs/graphics/sdl/sdl_common.h"
#include "libs/input/input_common.h"
Uint8 KeyboardDown[512]; Uint8 KeyboardDown[512];
@@ -48,6 +49,8 @@ TFB_InitInput (int driver, int flags)
int i; int i;
SDL_Joystick *Joystick1; SDL_Joystick *Joystick1;
atexit (TFB_UninitInput);
if ((SDL_InitSubSystem(SDL_INIT_JOYSTICK)) == -1) if ((SDL_InitSubSystem(SDL_INIT_JOYSTICK)) == -1)
{ {
fprintf (stderr, "Couldn't initialize joystick subsystem: %s\n", SDL_GetError()); fprintf (stderr, "Couldn't initialize joystick subsystem: %s\n", SDL_GetError());
@@ -86,6 +89,11 @@ TFB_InitInput (int driver, int flags)
return 0; return 0;
} }
void
TFB_UninitInput (void)
{
}
void void
ProcessKeyboardEvent(const SDL_Event *Event) ProcessKeyboardEvent(const SDL_Event *Event)
{ {
+2 -2
View File
@@ -3,7 +3,7 @@
# Written by Mudry <mudry@user.sf.net>, protected by GNU GPL. # Written by Mudry <mudry@user.sf.net>, protected by GNU GPL.
# CVS $ Id: $ # CVS $ Id: $
SUBDIRS = sdl SUBDIRS = openal
INCLUDES = @SDL_CFLAGS@ \ INCLUDES = @SDL_CFLAGS@ \
-I$(top_srcdir)/src \ -I$(top_srcdir)/src \
@@ -12,6 +12,6 @@ INCLUDES = @SDL_CFLAGS@ \
noinst_LTLIBRARIES = libsound.la noinst_LTLIBRARIES = libsound.la
libsound_la_SOURCES = fileinst.c resinst.c sound_common.c 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 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 int
TFB_InitSound (int driver, int flags, int frequency) 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]; char SoundcardName[256];
int audio_rate,audio_channels; int audio_rate,audio_channels;
Uint16 audio_format; Uint16 audio_format;
SDL_version compile_version; SDL_version compile_version;
fprintf (stderr, "Initializing SDL audio subsystem.\n");
if ((SDL_InitSubSystem(SDL_INIT_AUDIO)) == -1) if ((SDL_InitSubSystem(SDL_INIT_AUDIO)) == -1)
{ {
fprintf (stderr, "Couldn't initialize audio subsystem: %s\n", SDL_GetError()); fprintf (stderr, "Couldn't initialize audio subsystem: %s\n", SDL_GetError());
exit(-1); exit(-1);
} }
fprintf (stderr, "SDL audio subsystem initialized.\n");
fprintf (stderr, "Initializing SDL_mixer.\n");
if (Mix_OpenAudio(frequency, AUDIO_S16, 2, 2048)) if (Mix_OpenAudio(frequency, AUDIO_S16, 2, 2048))
{ {
fprintf (stderr, "Unable to open audio: %s\n", Mix_GetError()); fprintf (stderr, "Unable to open audio: %s\n", Mix_GetError());
exit (-1); exit (-1);
} }
fprintf (stderr, "SDL_mixer initialized.\n");
atexit (Mix_CloseAudio); 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()) if (!Sound_Init())
{ {
fprintf(stderr, "Sound_Init() failed: %s\n", Sound_GetError()); fprintf(stderr, "Sound_Init() failed: %s\n", Sound_GetError());
exit (-1); exit (-1);
} }
fprintf (stderr, "SDL_sound initialized.\n");
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);
return 0; return 0;
} }
+6 -3
View File
@@ -20,7 +20,10 @@
#include "libs/sound/sound_common.h" #include "libs/sound/sound_common.h"
#include "libs/tasklib.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 Task FadeTask;
static SIZE TTotal; static SIZE TTotal;
@@ -33,7 +36,7 @@ fade_task (void *data)
DWORD StartTime, CurTime; DWORD StartTime, CurTime;
Task task = (Task) data; Task task = (Task) data;
volume_beg = _music_volume; volume_beg = musicVolume;
StartTime = CurTime = GetTimeCounter (); StartTime = CurTime = GetTimeCounter ();
do do
{ {
@@ -58,7 +61,7 @@ FadeMusic (BYTE end_vol, SIZE TimeInterval)
if (FadeTask) if (FadeTask)
{ {
volume_end = _music_volume; volume_end = musicVolume;
TTotal = 1; TTotal = 1;
do do
TaskSwitch (); TaskSwitch ();
@@ -29,5 +29,11 @@ enum
//#define TFB_SOUNDFLAGS_ETC (1<<0) //#define TFB_SOUNDFLAGS_ETC (1<<0)
int TFB_InitSound (int driver, int flags, int frequency); 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 #endif
+40 -4
View File
@@ -61,6 +61,7 @@ main (int argc, char *argv[])
int gfxflags = 0; int gfxflags = 0;
int width = 640, height = 480, bpp = 16; int width = 640, height = 480, bpp = 16;
int frequency = 44100; int frequency = 44100;
int vol;
char contentdir[1000]; char contentdir[1000];
int option_index = 0, c; int option_index = 0, c;
@@ -76,6 +77,9 @@ main (int argc, char *argv[])
{"tv", 0, NULL, 't'}, {"tv", 0, NULL, 't'},
{"contentdir", 1, NULL, 'c'}, {"contentdir", 1, NULL, 'c'},
{"help", 0, NULL, 'h'}, {"help", 0, NULL, 'h'},
{"musicvol", 1, NULL, 'M'},
{"sfxvol", 1, NULL, 'S'},
{"speechvol", 1, NULL, 'T'},
{0, 0, 0, 0} {0, 0, 0, 0}
}; };
@@ -85,7 +89,7 @@ main (int argc, char *argv[])
strcpy (contentdir, "../../content"); strcpy (contentdir, "../../content");
#endif #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) { switch (c) {
case 'r': case 'r':
@@ -115,6 +119,30 @@ main (int argc, char *argv[])
case 'c': case 'c':
sscanf(optarg, "%s", contentdir); sscanf(optarg, "%s", contentdir);
break; 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: default:
printf ("\nOption %s not found!\n", long_options[option_index].name); printf ("\nOption %s not found!\n", long_options[option_index].name);
case '?': case '?':
@@ -122,7 +150,7 @@ main (int argc, char *argv[])
printf("\nThe Ur-Quan Masters\n"); printf("\nThe Ur-Quan Masters\n");
printf("Options:\n"); printf("Options:\n");
printf(" -r, --res=WIDTHxHEIGHT\n"); printf(" -r, --res=WIDTHxHEIGHT\n");
printf(" -d, --bpp=BITSPERPLANE\n"); printf(" -d, --bpp=BITSPERPIXEL\n");
printf(" -f, --fullscreen\n"); printf(" -f, --fullscreen\n");
printf(" -o, --opengl\n"); printf(" -o, --opengl\n");
printf(" -b, --bilinear\n"); printf(" -b, --bilinear\n");
@@ -130,6 +158,9 @@ main (int argc, char *argv[])
printf(" -p, --fps\n"); printf(" -p, --fps\n");
printf(" -t, --tv\n"); printf(" -t, --tv\n");
printf(" -c, --contentdir=CONTENTDIR\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; return 0;
break; break;
} }
@@ -140,11 +171,16 @@ main (int argc, char *argv[])
InitThreadSystem (); InitThreadSystem ();
InitTimeSystem (); InitTimeSystem ();
InitTaskSystem (); InitTaskSystem ();
_MemorySem = CreateSemaphore (1);
GraphicsSem = CreateSemaphore (1);
mem_init ();
TFB_InitGraphics (gfxdriver, gfxflags, width, height, bpp); TFB_InitGraphics (gfxdriver, gfxflags, width, height, bpp);
TFB_InitSound (TFB_SOUNDDRIVER_SDL, 0, frequency); TFB_InitSound (TFB_SOUNDDRIVER_SDL, 0, frequency);
TFB_InitInput (TFB_INPUTDRIVER_SDL, 0); TFB_InitInput (TFB_INPUTDRIVER_SDL, 0);
TFB_CreateGamePlayThread (); AssignTask (Starcon2Main, 1024, "Starcon2Main");
for (;;) for (;;)
{ {
@@ -152,5 +188,5 @@ main (int argc, char *argv[])
TFB_FlushGraphics (); TFB_FlushGraphics ();
} }
return 0; exit(0);
} }