Fix OpenAL channel allocation handling.
This patch corrects the OpenAL setup logic to explicitly request the
number of channels expected by Aquaria, and to limit the number of
channels actually exported to the number returned by the OpenAL
implementation. This fixes incorrect behavior (such as delayed sounds
or crashing) when the system defaults to less than 128 channels.
--- a/BBGE/FmodOpenALBridge.cpp Sat Jul 10 15:04:54 2010 +0900
+++ b/BBGE/FmodOpenALBridge.cpp Sat Feb 19 11:56:14 2011 +0900
@@ -509,7 +509,7 @@
public:
OpenALSystem();
~OpenALSystem();
- FMOD_RESULT init(const int maxchannels, const FMOD_INITFLAGS flags, const void *extradriverdata);
+ FMOD_RESULT init(int maxchannels, const FMOD_INITFLAGS flags, const void *extradriverdata);
FMOD_RESULT update();
FMOD_RESULT release();
FMOD_RESULT getVersion(unsigned int *version);
@@ -524,6 +524,8 @@
FMOD_RESULT getMasterChannelGroup(ChannelGroup **channelgroup);
FMOD_RESULT playSound(FMOD_CHANNELINDEX channelid, Sound *sound, bool paused, Channel **channel);
+ FMOD_RESULT getNumChannels(int *maxchannels_ret);
+
private:
OpenALChannelGroup *master_channel_group;
int num_channels;
@@ -732,19 +734,68 @@
}
ALBRIDGE(System,init,(int maxchannels, FMOD_INITFLAGS flags, void *extradriverdata),(maxchannels,flags,extradriverdata))
-FMOD_RESULT OpenALSystem::init(const int maxchannels, const FMOD_INITFLAGS flags, const void *extradriverdata)
+FMOD_RESULT OpenALSystem::init(int maxchannels, const FMOD_INITFLAGS flags, const void *extradriverdata)
{
ALCdevice *dev = alcOpenDevice(NULL);
if (!dev)
return FMOD_ERR_INTERNAL;
- ALCcontext *ctx = alcCreateContext(dev, NULL);
+ // OpenAL doesn't provide a way to request sources that can be either
+ // mono or stereo, so we need to request both separately (thus allocating
+ // twice the theoretical requirement -- oh well). --achurch
+ ALCint requested_attributes[5];
+ requested_attributes[0] = ALC_MONO_SOURCES;
+ requested_attributes[1] = maxchannels;
+ requested_attributes[2] = ALC_STEREO_SOURCES;
+ requested_attributes[3] = maxchannels;
+ requested_attributes[4] = 0;
+ ALCcontext *ctx = alcCreateContext(dev, requested_attributes);
if (!ctx)
{
alcCloseDevice(dev);
return FMOD_ERR_INTERNAL;
}
+ ALCint num_attributes = 0;
+ alcGetIntegerv(dev, ALC_ATTRIBUTES_SIZE, 1, &num_attributes);
+ if (num_attributes > 0) {
+ ALCint *attributes = new ALCint[num_attributes];
+ alcGetIntegerv(dev, ALC_ALL_ATTRIBUTES, num_attributes, attributes);
+ int i;
+ for (i = 0; i < num_attributes; i += 2) {
+ if (attributes[i] == ALC_MONO_SOURCES) {
+ if (attributes[i+1] <= 0) {
+ debugLog("Couldn't get any mono sources, aborting");
+ alcDestroyContext(ctx);
+ alcCloseDevice(dev);
+ return FMOD_ERR_INTERNAL;
+ } else if (attributes[i+1] < num_channels) {
+ std::ostringstream os;
+ os << "Only got " << attributes[i+1] << " of "
+ << maxchannels << " mono sources";
+ debugLog(os.str());
+ maxchannels = attributes[i+1];
+ }
+ } else if (attributes[i] == ALC_STEREO_SOURCES) {
+ if (attributes[i+1] <= 0) {
+ debugLog("Couldn't get any stereo sources, aborting");
+ alcDestroyContext(ctx);
+ alcCloseDevice(dev);
+ return FMOD_ERR_INTERNAL;
+ } else if (attributes[i+1] < num_channels) {
+ std::ostringstream os;
+ os << "Only got " << attributes[i+1] << " of "
+ << maxchannels << " stereo sources";
+ debugLog(os.str());
+ maxchannels = attributes[i+1];
+ }
+ }
+ }
+ delete[] attributes;
+ } else {
+ debugLog("WARNING: couldn't get device attributes!");
+ }
+
alcMakeContextCurrent(ctx);
alcProcessContext(ctx);
@@ -789,6 +840,13 @@
return FMOD_OK;
}
+ALBRIDGE(System,getNumChannels,(int *maxchannels_ret),(maxchannels_ret))
+FMOD_RESULT OpenALSystem::getNumChannels(int *maxchannels_ret)
+{
+ *maxchannels_ret = num_channels;
+ return FMOD_OK;
+}
+
ALBRIDGE(System,playSound,(FMOD_CHANNELINDEX channelid, Sound *sound, bool paused, Channel **channel),(channelid,sound,paused,channel))
FMOD_RESULT OpenALSystem::playSound(FMOD_CHANNELINDEX channelid, Sound *_sound, bool paused, Channel **channel)
{
--- a/BBGE/FmodOpenALBridge.h Sat Jul 10 15:04:54 2010 +0900
+++ b/BBGE/FmodOpenALBridge.h Sat Feb 19 11:56:14 2011 +0900
@@ -164,6 +164,9 @@
FMOD_RESULT setFileSystem(FMOD_FILE_OPENCALLBACK useropen, FMOD_FILE_CLOSECALLBACK userclose, FMOD_FILE_READCALLBACK userread, FMOD_FILE_SEEKCALLBACK userseek, int blockalign);
FMOD_RESULT setSpeakerMode(FMOD_SPEAKERMODE speakermode);
FMOD_RESULT update();
+
+ // BBGE-specific...
+ FMOD_RESULT getNumChannels(int *maxchannels_ret);
};
typedef System FMOD_SYSTEM;
--- a/BBGE/SoundManager.cpp Sat Jul 10 15:04:54 2010 +0900
+++ b/BBGE/SoundManager.cpp Sat Feb 19 11:56:14 2011 +0900
@@ -336,7 +336,10 @@
if (checkError()) goto get_out;
}
-
+#ifdef BBGE_BUILD_FMOD_OPENAL_BRIDGE
+ SoundCore::system->getNumChannels(&channels);
+#endif
+
//FMOD::Debug_SetLevel(FMOD_DEBUG_LEVEL_ALL);
/*