Add OpenAL implementation of C4SoundSystem

With an Ogg Vorbis loader using libvorbis and a .wav loader using a macosx
API.

Günther: Add autotools support
floating-point
Martin Plicht 2010-09-26 02:36:35 +02:00
parent f327022edd
commit 243e20bdf6
10 changed files with 540 additions and 57 deletions

View File

@ -428,6 +428,8 @@ set(OC_CLONK_SOURCES
src/platform/C4MusicSystem.h
src/platform/C4SoundSystem.cpp
src/platform/C4SoundSystem.h
src/platform/C4SoundLoaders.h
src/platform/C4SoundLoaders.cpp
src/platform/C4Video.cpp
src/platform/C4Video.h
src/platform/C4VideoPlayback.cpp

View File

@ -59,7 +59,7 @@ AM_CPPFLAGS = \
-I$(srcdir)/src/game/object \
-I$(srcdir)/src/lib/texture \
-I$(srcdir)/src/script \
$(GLEW_CFLAGS) $(GTK_CFLAGS) $(FREETYPE_CFLAGS) $(SDL_CFLAGS) $(BOOST_CPPFLAGS)
$(GLEW_CFLAGS) $(GTK_CFLAGS) $(OPENAL_CFLAGS) $(FREETYPE_CFLAGS) $(SDL_CFLAGS) $(BOOST_CPPFLAGS)
##BUILT_SOURCES = hgrevision.h
##hgrevision.h: $(srcdir)/.hg/dirstate
@ -428,6 +428,8 @@ src/platform/C4MusicSystem.cpp \
src/platform/C4MusicSystem.h \
src/platform/C4SoundSystem.cpp \
src/platform/C4SoundSystem.h \
src/platform/C4SoundLoaders.h \
src/platform/C4SoundLoaders.cpp \
src/platform/C4Video.cpp \
src/platform/C4Video.h \
src/platform/C4VideoPlayback.cpp \
@ -547,6 +549,7 @@ clonk_LDADD = \
lib.a \
$(LIBICONV) \
$(GTK_LIBS) \
$(OPENAL_LIBS) \
$(FREETYPE_LIBS) \
$(SDL_LIBS) \
$(PTHREAD_LIBS) \

View File

@ -172,6 +172,9 @@
/* MP3 music */
#undef USE_MP3
/* OpenAL sound */
#undef USE_OPEN_AL
/* Define to 1 if SDL is used for the main loop */
#undef USE_SDL_MAINLOOP

View File

@ -15,7 +15,7 @@ dnl Process this file with autoconf to produce a configure script.
AC_PREREQ(2.59)
AC_INIT(clonk, m4_format([[[%s.%s.%s.%s]]], m4_include(version)))
AC_COPYRIGHT([©2005-2009 Günther Brammer])
AC_COPYRIGHT([©2005-2010 Günther Brammer])
AC_CONFIG_SRCDIR([/src/C4Game.cpp])
AC_CONFIG_AUX_DIR([autotools])
AC_CONFIG_HEADER([config.h])
@ -115,6 +115,21 @@ AS_IF([test $with_gtk = yes],[
])
AM_CONDITIONAL(DEVELOPER_MODE, [test $with_gtk = yes])
# OpenAL
AC_ARG_WITH([openal],
[AC_HELP_STRING([--with-openal],[compile with openal support [default=no]])],
, [with_openal=no])
if test $with_openal = yes; then
PKG_CHECK_MODULES(OPENAL, [vorbis vorbisfile openal])
AC_DEFINE([USE_OPEN_AL], 1, [OpenAL sound])
if test $enable_sound = no; then
AC_MSG_ERROR([--with-openal cannot be used with --disable-sound.])
fi
fi
# SDL
with_sdl_mixer=no
AC_ARG_WITH([sdl],
AS_HELP_STRING([--with-sdl], [Use SDL @<:@default=yes (no for win32)@:>@]),
, [if test $win32 = true; then with_sdl=no; else if test $enable_console = yes; then with_sdl=no; else with_sdl=yes; fi fi])
@ -126,11 +141,12 @@ if test $with_sdl = yes; then
[AC_MSG_ERROR([libSDL not found.])])
AC_SUBST(SDL_CFLAGS)
AC_SUBST(SDL_LIBS)
if test $enable_sound = yes; then
if test $enable_sound = yes && test $with_openal = no; then
# Check for SDL_mixer library
AC_CHECK_LIB(SDL_mixer, Mix_OpenAudio,
[AC_DEFINE(HAVE_LIBSDL_MIXER,1,[Define to 1 if you have SDL_mixer.])
SDL_LIBS="-lSDL_mixer $SDL_LIBS"],
SDL_LIBS="-lSDL_mixer $SDL_LIBS"
with_sdl_mixer=yes],
[AC_MSG_ERROR([SDL_mixer not found.])],
[$SDL_LIBS])
fi
@ -172,6 +188,10 @@ AX_BOOST_BASE([1.40.0], [], [
AC_MSG_ERROR([Boost not found.])
])
# OpenSSL
AC_CHECK_LIB(crypto, BIO_new, [OPENSSL_LIBS="-lcrypto"],
[AC_MSG_ERROR([libcrypto (OpenSSL) not found.])])
# Check for libjpeg
AC_CHECK_LIB(jpeg, jpeg_read_header, [
CLONK_LIBS="-ljpeg $CLONK_LIBS"
@ -262,10 +282,6 @@ if test "$with_directx" = yes; then
AC_DEFINE([USE_DIRECTX], 1, [DirectX graphics])
fi
# OpenSSL
AC_CHECK_LIB(crypto, BIO_new, [OPENSSL_LIBS="-lcrypto"],
[AC_MSG_ERROR([libcrypto (OpenSSL) not found.])])
if test $win32 = false; then
# pthread
AX_PTHREAD( , [AC_MSG_ERROR([No pthread support.])])
@ -323,6 +339,8 @@ echo "Configuration:
DirectX: $with_directx
OpenGL: $with_gl
Sound: $enable_sound
SDL_Mixer: $with_sdl_mixer
OpenAL: $with_openal
GTK+: $with_gtk
X11: $have_x"

View File

@ -54,6 +54,9 @@ C4MusicSystem::C4MusicSystem():
SongCount(0),
PlayMusicFile(NULL),
Volume(100)
#ifdef USE_OPEN_AL
, alcDevice(NULL), alcContext(NULL)
#endif
{
}
@ -62,6 +65,13 @@ C4MusicSystem::~C4MusicSystem()
Clear();
}
#ifdef USE_OPEN_AL
void C4MusicSystem::SelectContext()
{
alcMakeContextCurrent(alcContext);
}
#endif
bool C4MusicSystem::InitializeMOD()
{
#if defined HAVE_FMOD
@ -117,6 +127,14 @@ bool C4MusicSystem::InitializeMOD()
}
MODInitialized = true;
return true;
#elif defined(USE_OPEN_AL)
alcDevice = alcOpenDevice(NULL);
if (!alcDevice)
return false;
alcContext = alcCreateContext(alcDevice, NULL);
if (!alcContext)
return false;
return true;
#endif
return false;
}
@ -132,6 +150,11 @@ void C4MusicSystem::DeinitializeMOD()
#elif defined HAVE_LIBSDL_MIXER
Mix_CloseAudio();
SDL_Quit();
#elif defined(USE_OPEN_AL)
alcDestroyContext(alcContext);
alcCloseDevice(alcDevice);
alcContext = NULL;
alcDevice = NULL;
#endif
MODInitialized = false;
}

View File

@ -27,6 +27,16 @@
#include <C4Group.h>
#if defined(USE_OPEN_AL)
#ifdef __APPLE__
#import <OpenAL/al.h>
#import <OpenAL/alc.h>
#else
#include <AL/al.h>
#include <AL/alc.h>
#endif
#endif
class C4MusicFileInfoNode;
class C4MusicFile;
@ -68,10 +78,19 @@ protected:
bool GrpContainsMusic(C4Group &rGrp); // return whether this group contains music files
// FMod / SDL_mixer
// FMod / SDL_mixer / OpenAL
bool MODInitialized;
bool InitializeMOD();
void DeinitializeMOD();
#ifdef USE_OPEN_AL
private:
ALCdevice* alcDevice;
ALCcontext* alcContext;
public:
void SelectContext();
#endif
public:
inline bool IsMODInitialized() {return MODInitialized;}
};

View File

@ -0,0 +1,266 @@
/*
* OpenClonk, http://www.openclonk.org
*
* Copyright (c) 2010 Mortimer
* Copyright (c) 2003-2004 Peter Wortmann
* Copyright (c) 2005-2006, 2008 Sven Eberhardt
* Copyright (c) 2005-2006 Günther Brammer
* Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de
*
* Portions might be copyrighted by other authors who have contributed
* to OpenClonk.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
* See isc_license.txt for full license and disclaimer.
*
* "Clonk" is a registered trademark of Matthes Bender.
* See clonk_trademark_license.txt for full license.
*/
#include <C4Include.h>
#include "C4SoundLoaders.h"
#if defined(USE_OPEN_AL) && defined(__APPLE__)
#import <CoreFoundation/CoreFoundation.h>
#import <AudioToolbox/AudioToolbox.h>
#endif
#ifdef USE_OPEN_AL
extern "C"
{
#include <vorbis/codec.h>
#include <vorbis/vorbisfile.h>
}
#endif
using namespace C4SoundLoaders;
SoundLoader* SoundLoader::first_loader(NULL);
#if defined(USE_OPEN_AL) && defined(__APPLE__)
namespace
{
static OSStatus AudioToolBoxReadCallback(void* context, SInt64 inPosition, UInt32 requestCount, void* buffer, UInt32* actualCount)
{
CFDataRef audio = (CFDataRef)context;
CFIndex audio_length = CFDataGetLength(audio);
int requestOffset = inPosition + requestCount;
int availableBytes = audio_length - inPosition;
if (requestOffset > audio_length) {
*actualCount = availableBytes;
} else {
*actualCount = requestCount;
}
CFRange range;
range.location = inPosition;
range.length = *actualCount;
CFDataGetBytes(audio, range, (UInt8*)buffer);
return noErr;
}
static SInt64 AudioToolBoxGetSizeProc(void* context)
{
return CFDataGetLength((CFDataRef)context);
}
}
bool AppleSoundLoader::ReadInfo(SoundInfo& info, BYTE* data, size_t data_length, uint32_t)
{
CFDataRef data_container = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, data, data_length, kCFAllocatorNull);
AudioFileID sound_file;
OSStatus err = AudioFileOpenWithCallbacks((void*)data_container,
AudioToolBoxReadCallback,
NULL,
AudioToolBoxGetSizeProc,
NULL,
0,
&sound_file
);
if (err == noErr)
{
UInt32 property_size;
info.sound_data_size = 0;
property_size = sizeof(info.sound_data_size);
AudioFileGetProperty(sound_file, kAudioFilePropertyAudioDataByteCount, &property_size, &info.sound_data_size);
info.sample_length = -1;
property_size = sizeof(info.sample_length);
AudioFileGetProperty(sound_file, kAudioFilePropertyEstimatedDuration, &property_size, &info.sample_length);
UInt32 sound_data_size_32 = info.sound_data_size;
info.sound_data = malloc(info.sound_data_size);
AudioFileReadBytes(sound_file, false, 0, &sound_data_size_32, info.sound_data);
AudioStreamBasicDescription desc;
property_size = sizeof(desc);
AudioFileGetProperty(sound_file, kAudioFilePropertyDataFormat, &property_size, &desc);
info.sample_rate = desc.mSampleRate;
switch (desc.mChannelsPerFrame)
{
case 1:
info.format = desc.mBitsPerChannel == 16 ? AL_FORMAT_MONO16 : AL_FORMAT_MONO8;
break;
case 2:
info.format = desc.mBitsPerChannel == 16 ? AL_FORMAT_STEREO16 : AL_FORMAT_STEREO8;
break;
default:
info.format = 0;
}
}
CFRelease(data_container);
return err == noErr;
}
AppleSoundLoader AppleSoundLoader::singleton;
#endif
#ifdef USE_OPEN_AL
size_t VorbisLoader::read_func(void* ptr, size_t byte_size, size_t size_to_read, void* datasource)
{
size_t spaceToEOF;
size_t actualSizeToRead;
VorbisLoader* loader = (VorbisLoader*)datasource;
spaceToEOF = loader->data_length - loader->data_pos;
if (size_to_read*byte_size < spaceToEOF)
actualSizeToRead = size_to_read*byte_size;
else
actualSizeToRead = spaceToEOF;
if (actualSizeToRead)
{
memcpy(ptr, (char*)loader->data + loader->data_pos, actualSizeToRead);
loader->data_pos += actualSizeToRead;
}
return actualSizeToRead;
}
int VorbisLoader::seek_func(void* datasource, ogg_int64_t offset, int whence)
{
size_t spaceToEOF;
ogg_int64_t actualOffset; // How much we can actually offset it by
VorbisLoader* loader = (VorbisLoader*)datasource;
switch (whence)
{
case SEEK_SET:
loader->data_pos = offset < loader->data_length ? offset : loader->data_length;
break;
case SEEK_CUR:
loader->data_pos += offset < loader->data_length - loader->data_pos ? offset : loader->data_length - loader->data_pos;
break;
case SEEK_END:
loader->data_pos = loader->data_length+1;
break;
}
return 0;
}
int VorbisLoader::close_func(void* datasource)
{
return 1;
}
long VorbisLoader::tell_func(void* datasource)
{
return ((VorbisLoader*)datasource)->data_pos;
}
bool VorbisLoader::ReadInfo(SoundInfo& result, BYTE* data, size_t data_length, uint32_t)
{
this->data = data;
this->data_length = data_length;
this->data_pos = 0;
int endian = 0;
int bitStream;
long bytes;
char array[32768];
vorbis_info* info;
OggVorbis_File ogg_file;
memset(&ogg_file, 0, sizeof(ogg_file));
ov_callbacks callbacks;
callbacks.read_func = &read_func;
callbacks.seek_func = &seek_func;
callbacks.close_func = &close_func;
callbacks.tell_func = &tell_func;
// open using callbacks
if (ov_open_callbacks(this, &ogg_file, NULL, 0, callbacks) != 0)
{
ov_clear(&ogg_file);
return false;
}
info = ov_info(&ogg_file, -1);
if (info->channels == 1)
result.format = AL_FORMAT_MONO16;
else
result.format = AL_FORMAT_STEREO16;
result.sample_rate = info->rate;
std::vector<BYTE> buffer;
do {
bytes = ov_read(&ogg_file, array, sizeof(array)/sizeof(array[0]), endian, 2, 1, &bitStream);
for (int i = 0; i < bytes; i++)
buffer.push_back(array[i]);
} while (bytes > 0);
result.sound_data = malloc(buffer.size());
result.sound_data_size = buffer.size();
for (int i = 0; i < buffer.size(); i++)
((BYTE*)result.sound_data)[i] = buffer[i];
result.sample_length = 5;
ov_clear(&ogg_file);
return true;
}
VorbisLoader VorbisLoader::singleton;
#endif
#ifdef HAVE_LIBSDL_MIXER
bool SDLMixerSoundLoader::ReadInfo(SoundInfo& result, BYTE* data, size_t data_length, uint32_t)
{
// Be paranoid about SDL_Mixer initialisation
if (!Application.MusicSystem.IsMODInitialized())
{ return false; }
if (!(result.final_handle = Mix_LoadWAV_RW(SDL_RWFromConstMem(data, data_length), 1)))
{ return false; }
//FIXME: Is this actually correct?
result.sample_length = result.final_handle->alen / (44100 * 2);
result.sample_rate = 0;
return true;
}
SDLMixerSoundLoader SDLMixerSoundLoader::singleton;
#endif
#ifdef HAVE_FMOD
bool FMODSoundLoader::ReadInfo(SoundInfo& result, BYTE* data, size_t data_length, uint32_t options)
{
int32_t iOptions = FSOUND_NORMAL | FSOUND_2D | FSOUND_LOADMEMORY;
if (options & OPTION_Raw)
iOptions |= FSOUND_LOADRAW;
SoundHandle pSample;
if (!(pSample = FSOUND_Sample_Load(FSOUND_UNMANAGED, (const char *)data, iOptions, 0, data_length)))
{ Clear(); return false; }
// get length
int32_t iSamples = FSOUND_Sample_GetLength(pSample);
int iSampleRate = SampleRate;
if (!iSamples || !FSOUND_Sample_GetDefaults(pSample, &iSampleRate, 0, 0, 0))
return false;
result.sample_rate = iSampleRate;
result.sample_length = iSamples / iSampleRate;
result.final_handle = pSample;
return true;
}
FMODSoundLoader FMODSoundLoader::singleton;
#endif

View File

@ -0,0 +1,109 @@
/*
* OpenClonk, http://www.openclonk.org
*
* Copyright (c) 2010 Mortimer
*
* Portions might be copyrighted by other authors who have contributed
* to OpenClonk.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
* See isc_license.txt for full license and disclaimer.
*
* "Clonk" is a registered trademark of Matthes Bender.
* See clonk_trademark_license.txt for full license.
*/
#ifdef USE_OPEN_AL
extern "C"
{
#include <vorbis/codec.h>
#include <vorbis/vorbisfile.h>
}
#endif
namespace C4SoundLoaders
{
struct SoundInfo
{
public:
double sample_length;
uint32_t sample_rate;
void* sound_data;
uint64_t sound_data_size;
#ifdef USE_OPEN_AL
ALenum format;
#endif
C4SoundHandle final_handle;
SoundInfo(): sound_data(NULL), final_handle(NULL) {}
~SoundInfo()
{
if (sound_data)
free(sound_data);
}
};
class SoundLoader
{
public:
static const int OPTION_Raw = 1;
public:
static SoundLoader* first_loader;
SoundLoader* next;
SoundLoader()
{
next = first_loader;
first_loader = this;
}
virtual bool ReadInfo(SoundInfo& info, BYTE* data, size_t data_length, uint32_t options = 0) = 0;
};
#if defined(USE_OPEN_AL) && defined(__APPLE__)
class AppleSoundLoader: public SoundLoader
{
public:
AppleSoundLoader(): SoundLoader() {}
virtual bool ReadInfo(SoundInfo& info, BYTE* data, size_t data_length, uint32_t);
protected:
static AppleSoundLoader singleton;
};
#endif
#ifdef USE_OPEN_AL
class VorbisLoader: public SoundLoader
{
private:
BYTE* data;
size_t data_length;
size_t data_pos;
static size_t read_func(void* ptr, size_t byte_size, size_t size_to_read, void* datasource);
static int seek_func(void* datasource, ogg_int64_t offset, int whence);
static int close_func(void* datasource);
static long tell_func(void* datasource);
public:
virtual bool ReadInfo(SoundInfo& result, BYTE* data, size_t data_length, uint32_t);
protected:
static VorbisLoader singleton;
};
#endif
#ifdef HAVE_LIBSDL_MIXER
class SDLMixerSoundLoader: public SoundLoader
{
public:
static SDLMixerSoundLoader singleton;
virtual bool ReadInfo(SoundInfo& result, BYTE* data, size_t data_length, uint32_t);
};
#endif
#ifdef HAVE_FMOD
class FMODSoundLoader: public SoundLoader
{
public:
static FMODSoundLoader singleton;
virtual bool ReadInfo(SoundInfo& result, BYTE* data, size_t data_length, uint32_t options);
};
#endif
}

View File

@ -30,14 +30,15 @@
#include <C4Config.h>
#include <C4Application.h>
#include <C4GraphicsSystem.h>
#include <C4SoundLoaders.h>
using namespace C4SoundLoaders;
C4SoundEffect::C4SoundEffect():
UsageTime (0),
Instances (0),
Static (false),
#if defined HAVE_FMOD || defined HAVE_LIBSDL_MIXER
pSample (NULL),
#endif
FirstInst (NULL),
Next (NULL)
{
@ -58,9 +59,10 @@ void C4SoundEffect::Clear()
#ifdef HAVE_LIBSDL_MIXER
if (pSample) Mix_FreeChunk(pSample);
#endif
#if defined HAVE_FMOD || defined HAVE_LIBSDL_MIXER
pSample = NULL;
#ifdef USE_OPEN_AL
if (pSample) alDeleteBuffers(1, &pSample);
#endif
pSample = NULL;
}
bool C4SoundEffect::Load(const char *szFileName, C4Group &hGroup, bool fStatic)
@ -81,36 +83,40 @@ bool C4SoundEffect::Load(BYTE *pData, size_t iDataLen, bool fStatic, bool fRaw)
{
// Sound check
if (!Config.Sound.RXSound) return false;
// load directly from memory
#ifdef HAVE_FMOD
int32_t iOptions = FSOUND_NORMAL | FSOUND_2D | FSOUND_LOADMEMORY;
if (fRaw) iOptions |= FSOUND_LOADRAW;
if (!(pSample = FSOUND_Sample_Load(FSOUND_UNMANAGED, (const char *)pData,
iOptions, 0, iDataLen)))
{ Clear(); return false; }
// get length
int32_t iSamples = FSOUND_Sample_GetLength(pSample);
int iSampleRate = SampleRate;
if (!iSamples || !FSOUND_Sample_GetDefaults(pSample, &iSampleRate, 0, 0, 0))
return false;
SampleRate = iSampleRate;
Length = iSamples * 10 / (SampleRate / 100);
#endif
#ifdef HAVE_LIBSDL_MIXER
// Be paranoid about SDL_Mixer initialisation
if (!Application.MusicSystem.MODInitialized)
{ Clear(); return false; }
if (!(pSample = Mix_LoadWAV_RW(SDL_RWFromConstMem(pData, iDataLen), 1)))
{ Clear(); return false; }
//FIXME: Is this actually correct?
Length = 1000 * pSample->alen / (44100 * 2);
SampleRate = 0;
SoundInfo info;
int32_t options = 0;
if (fRaw)
options |= SoundLoader::OPTION_Raw;
for (SoundLoader* loader = SoundLoader::first_loader; loader; loader = loader->next)
{
if (loader->ReadInfo(info, pData, iDataLen))
{
if (info.final_handle)
{
// loader supplied the handle specific to the sound system used; just assign to pSample
pSample = info.final_handle;
}
else
{
#ifdef USE_OPEN_AL
Application.MusicSystem.SelectContext();
alGenBuffers(1, &pSample);
alBufferData(pSample, info.format, info.sound_data, info.sound_data_size, info.sample_rate);
#else
Log("SoundLoader does not provide a ready-made handle");
#endif
}
SampleRate = info.sample_rate;
Length = info.sample_length*1000;
break;
}
}
*Name = '\0';
// Set usage time
UsageTime=Game.Time;
Static=fStatic;
return true;
return pSample;
}
void C4SoundEffect::Execute()
@ -270,6 +276,11 @@ bool C4SoundInstance::Start()
if (!Application.MusicSystem.MODInitialized) return false;
if ((iChannel = Mix_PlayChannel(-1, pEffect->pSample, fLooping? -1 : 0)) == -1)
return false;
#elif defined(USE_OPEN_AL)
Application.MusicSystem.SelectContext();
alGenSources(1, (ALuint*)&iChannel);
alSourcei(iChannel, AL_BUFFER, pEffect->pSample);
alSourcePlay(iChannel);
#else
return false;
#endif
@ -291,6 +302,10 @@ bool C4SoundInstance::Stop()
// iChannel == -1 will halt all channels. Is that right?
if (Playing())
Mix_HaltChannel(iChannel);
#endif
#ifdef USE_OPEN_AL
if (Playing())
alSourceStop(iChannel);
#endif
iChannel = -1;
iStarted = 0;
@ -308,6 +323,16 @@ bool C4SoundInstance::Playing()
#endif
#ifdef HAVE_LIBSDL_MIXER
return Application.MusicSystem.MODInitialized && (iChannel != -1) && Mix_Playing(iChannel);
#endif
#ifdef USE_OPEN_AL
if (iChannel == -1)
return false;
else
{
ALint state;
alGetSourcei(iChannel, AL_SOURCE_STATE, &state);
return state == AL_PLAYING;
}
#endif
return false;
}
@ -341,6 +366,9 @@ void C4SoundInstance::Execute()
#endif
#ifdef HAVE_LIBSDL_MIXER
Mix_HaltChannel(iChannel);
#endif
#ifdef USE_OPEN_AL
alDeleteSources(1, (ALuint*)&iChannel);
#endif
iChannel = -1;
}
@ -360,6 +388,10 @@ void C4SoundInstance::Execute()
Mix_Volume(iChannel, (iVol * MIX_MAX_VOLUME) / (100 * 256));
//Mix_SetPanning(iChannel, ((100 + iPan) * 256) / 200, ((100 - iPan) * 256) / 200);
Mix_SetPanning(iChannel, BoundBy((100 - iPan) * 256 / 100, 0, 255), BoundBy((100 + iPan) * 256 / 100, 0, 255));
#endif
#ifdef USE_OPEN_AL
alSource3f(iChannel, AL_POSITION, 0, 0, 0); // FIXME
alSourcef(iChannel, AL_GAIN, iVol / 100);
#endif
}
}
@ -439,6 +471,9 @@ void C4SoundSystem::ClearEffects()
void C4SoundSystem::Execute()
{
#ifdef USE_OPEN_AL
Application.MusicSystem.SelectContext();
#endif
// Sound effect statistics & unload check
C4SoundEffect *csfx,*next=NULL,*prev=NULL;
for (csfx=FirstSound; csfx; csfx=next)

View File

@ -26,23 +26,33 @@
#include <C4Group.h>
#ifdef HAVE_FMOD
#include <fmod.h>
#endif
#ifdef HAVE_LIBSDL_MIXER
#define USE_RWOPS
#include <SDL_mixer.h>
#undef USE_RWOPS
#endif
const int32_t C4MaxSoundName=100,
C4MaxSoundInstances=20,
C4NearSoundRadius=50,
C4AudibilityRadius=700;
const int32_t
C4MaxSoundName=100,
C4MaxSoundInstances=20,
C4NearSoundRadius=50,
C4AudibilityRadius=700;
class C4Object;
class C4SoundInstance;
#if defined(HAVE_FMOD)
#include <fmod.h>
typedef FSOUND_SAMPLE* C4SoundHandle;
#elif defined(HAVE_LIBSDL_MIXER)
#define USE_RWOPS
#include <SDL_mixer.h>
typedef Mix_Chunk* C4SoundHandle;
#elif defined(USE_OPEN_AL)
#ifdef __APPLE__
#import <OpenAL/al.h>
#else
#include <AL/al.h>
#endif
typedef ALuint C4SoundHandle;
#else
typedef void* C4SoundHandle;
#endif
class C4SoundEffect
{
friend class C4SoundInstance;
@ -54,12 +64,7 @@ public:
int32_t UsageTime, Instances;
int32_t SampleRate, Length;
bool Static;
#ifdef HAVE_FMOD
FSOUND_SAMPLE *pSample;
#endif
#ifdef HAVE_LIBSDL_MIXER
Mix_Chunk * pSample;
#endif
C4SoundHandle pSample;
C4SoundInstance *FirstInst;
C4SoundEffect *Next;
public: