Added sound culling (experimental), and various fixes

git-svn-id: https://openmw.svn.sourceforge.net/svnroot/openmw/trunk@27 ea6a568a-9f4f-0410-981a-c910a81bb256
actorid
nkorslund 16 years ago
parent e56c51b03e
commit 1e41012ff3

@ -9,7 +9,7 @@ DMD=gdmd -version=Posix
NIFFLAGS=
# Compiler settings for Ogre + OIS. Change as needed.
OGCC=$(CXX) $(CXXFLAGS) `pkg-config --cflags OGRE OIS openal`
OGCC=$(CXX) $(CXXFLAGS) `pkg-config --cflags OGRE OIS`
# Compiler settings for ffmpeg. Change as needed.
AVGCC=$(CXX) $(CXXFLAGS) `pkg-config --cflags libavcodec libavformat`

@ -113,7 +113,7 @@ Thanks goes out to:
- Bastien Jansen for continued testing on 64 bit linux.
- Chris Robinson for OpenAL and ALUT support
- Chris Robinson for OpenAL and MP3 support

@ -237,6 +237,8 @@ struct ConfigManager
bind(Keys.SfxVolUp, KC.N4);
bind(Keys.Mute, KC.M);
bind(Keys.Fullscreen, KC.F);
bind(Keys.ToggleBattleMusic, KC.SPACE);
bind(Keys.Debug, KC.G);

@ -90,6 +90,11 @@ void toggleBattle()
}
}
void toggleFullscreen()
{
cpp_toggleFullscreen();
}
const float volDiff = 0.05;
void musVolume(bool increase)
@ -212,6 +217,7 @@ extern(C) void d_handleKey(KC keycode, dchar text = 0)
case Keys.SfxVolUp: sfxVolume(true); break;
case Keys.SfxVolDown: sfxVolume(false); break;
case Keys.Mute: toggleMute(); break;
case Keys.Fullscreen: toggleFullscreen(); break;
case Keys.Debug: cpp_debug(0); break;
case Keys.ScreenShot: takeScreenShot(); break;
@ -265,16 +271,14 @@ bool isPressed(Keys key)
extern(C) int d_frameStarted(float time)
{
/*
tmpTime += time;
cnt++;
if(tmpTime >= 1.0)
if(tmpTime >= 1.5)
{
writefln("\nfps: ", cnt/tmpTime);
writefln("fps: ", cnt/tmpTime);
cnt = 0;
tmpTime = 0;
}
//*/
if(doExit) return 0;

@ -62,7 +62,8 @@ enum Keys
SfxVolUp, SfxVolDown,
Mute,
// This will not be part of the finished product :)
// These will not be part of the finished product
Fullscreen,
ToggleBattleMusic,
Debug,
@ -245,6 +246,7 @@ struct KeyBindings
keyToString[Keys.SfxVolDown] = "Decrease SFX Volume";
keyToString[Keys.Mute] = "Mute Sound";
keyToString[Keys.Fullscreen] = "Toggle Fullscreen Mode";
keyToString[Keys.ToggleBattleMusic] = "Toggle Battle Music";
keyToString[Keys.Debug] = "OGRE Test Action";

@ -137,6 +137,9 @@ void cpp_createMesh(
NodePtr owner // Scene node to attach to.
);
// Toggle fullscreen mode
void cpp_toggleFullscreen();
// Save a screen shot to the given file name
void cpp_screenshot(char *filename);

@ -215,9 +215,8 @@ extern "C" Light* cpp_attachLight(char *name, SceneNode* base,
l->setDiffuseColour(r,g,b);
// Pulled these numbers out of nowhere. Looks OK-ish. I can polish
// it later.
l->setAttenuation(8*radius, 0, 0.008, 0.0);
// This seems to look reasonably ok.
l->setAttenuation(3*radius, 0, 0, 12.0/(radius*radius));
// base might be null, sometimes lights don't have meshes
if(base) base->attachObject(l);
@ -225,6 +224,12 @@ extern "C" Light* cpp_attachLight(char *name, SceneNode* base,
return l;
}
// Toggle between fullscreen and windowed mode.
extern "C" void cpp_toggleFullscreen()
{
std::cout << "Not implemented yet\n";
}
extern "C" void cpp_setAmbient(float r, float g, float b, // Ambient light
float rs, float gs, float bs) // "Sunlight"
{

@ -29,6 +29,7 @@ Decrease Music Volume=1
Increase SFX Volume=4
Decrease SFX Volume=3
Mute Sound=m
Toggle Fullscreen Mode=f
Toggle Battle Music=space
OGRE Test Action=g
Pause=pause,p

@ -73,6 +73,10 @@ struct SoundList
float upx, float upy, float upz)
{
SoundInstance.setPlayerPos(x,y,z,frontx,fronty,frontz,upx,upy,upz);
foreach(ref s; list)
{
if(s.owner) s.updateSound();
}
}
void kill()

@ -54,11 +54,6 @@ void initializeSound()
alcMakeContextCurrent(Context);
// Gross HACK: We should use the default model (inverse distance clamped).
// But without a proper rolloff factor, distance attenuation is completely
// wrong. This at least makes sure the max distance is the 'silence' point
alDistanceModel(AL_LINEAR_DISTANCE_CLAMPED);
jukebox.initialize("Main");
battleMusic.initialize("Battle");
}
@ -75,11 +70,14 @@ void shutdownSound()
Device = null;
}
ALenum checkALError()
bool checkALError(char[] what = "")
{
ALenum err = alGetError();
if(what.length) what = " while " ~ what;
if(err != AL_NO_ERROR)
writefln("WARNING: Received AL error (%x): %s", err,
toString(alGetString(err)));
return err;
writefln("WARNING: OpenAL error%s: (%x) %s", what, err,
toString(alGetString(err)));
return err != AL_NO_ERROR;
}

@ -151,17 +151,19 @@ struct MusicManager
if(!sID)
{
alGenSources(1, &sID);
if(checkALError() != AL_NO_ERROR)
return;
if(checkALError())
fail("Couldn't generate music sources");
alSourcei(sID, AL_SOURCE_RELATIVE, AL_TRUE);
}
// Kill current track
alSourceStop(sID);
alSourcei(sID, AL_BUFFER, 0);
alDeleteBuffers(bIDs.length, bIDs.ptr);
foreach(ref b; bIDs) b = 0;
checkALError();
else
{
// Kill current track
alSourceStop(sID);
alSourcei(sID, AL_BUFFER, 0);
alDeleteBuffers(bIDs.length, bIDs.ptr);
bIDs[] = 0;
checkALError("killing current track");
}
if(fileHandle) cpp_closeAVFile(fileHandle);
fileHandle = null;
@ -175,35 +177,42 @@ struct MusicManager
}
alGenBuffers(bIDs.length, bIDs.ptr);
if(checkALError() != AL_NO_ERROR)
// If something fails, clean everything up.
scope(failure)
{
writefln("Unable to create %d buffers", bIDs.length);
if(fileHandle) cpp_closeAVFile(fileHandle);
fileHandle = null;
audioHandle = null;
alSourceStop(sID);
alDeleteSources(1, &sID);
checkALError();
alDeleteBuffers(bIDs.length, bIDs.ptr);
checkALError("cleaning up after music failure");
sID = 0;
return;
bIDs[] = 0;
// Try the next track if playNext is called again
index++;
}
if(checkALError())
fail("Couldn't generate buffers");
fileHandle = cpp_openAVFile(toStringz(playlist[index]));
if(!fileHandle)
{
writefln("Unable to open %s", playlist[index]);
goto errclose;
}
fail("Unable to open " ~ playlist[index]);
audioHandle = cpp_getAVAudioStream(fileHandle, 0);
if(!audioHandle)
{
writefln("Unable to load music track %s", playlist[index]);
goto errclose;
}
fail("Unable to load music track " ~ playlist[index]);
int ch, bits, rate;
if(cpp_getAVAudioInfo(audioHandle, &rate, &ch, &bits) != 0)
{
writefln("Unable to get info for music track %s", playlist[index]);
goto errclose;
}
fail("Unable to get info for music track " ~ playlist[index]);
bufRate = rate;
bufFormat = 0;
@ -221,24 +230,19 @@ struct MusicManager
}
if(bufFormat == 0)
{
writefln("Unhandled format (%d channels, %d bits) for music track %s", ch, bits, playlist[index]);
goto errclose;
}
fail(format("Unhandled format (%d channels, %d bits) for music track %s", ch, bits, playlist[index]));
foreach(int i, ref b; bIDs)
{
int length = cpp_getAVAudioData(audioHandle, outData.ptr, outData.length);
if(length) alBufferData(b, bufFormat, outData.ptr, length, bufRate);
if(length == 0 || checkALError() != AL_NO_ERROR)
if(length == 0 || checkALError())
{
if(i == 0)
{
writefln("No audio data in music track %s", playlist[index]);
goto errclose;
}
fail("No audio data in music track " ~ playlist[index]);
alDeleteBuffers(bIDs.length-i, bIDs.ptr+i);
checkALError();
checkALError("running alDeleteBuffers");
bIDs[i..$] = 0;
break;
}
@ -246,25 +250,11 @@ struct MusicManager
alSourceQueueBuffers(sID, bIDs.length, bIDs.ptr);
alSourcePlay(sID);
if(checkALError() != AL_NO_ERROR)
{
writefln("Unable to start music track %s", playlist[index]);
goto errclose;
}
if(checkALError())
fail("Unable to start music track " ~ playlist[index]);
index++;
return;
errclose:
if(fileHandle) cpp_closeAVFile(fileHandle);
fileHandle = null;
audioHandle = null;
alSourceStop(sID);
alDeleteSources(1, &sID);
alDeleteBuffers(bIDs.length, bIDs.ptr);
checkALError();
sID = 0;
foreach(ref b; bIDs) b = 0;
index++;
}
// Start playing the jukebox
@ -289,13 +279,13 @@ struct MusicManager
{
alSourceStop(sID);
alDeleteSources(1, &sID);
checkALError();
checkALError("disabling music");
sID = 0;
}
alDeleteBuffers(bIDs.length, bIDs.ptr);
checkALError();
foreach(ref b; bIDs) b = 0;
checkALError("deleting music buffers");
bIDs[] = 0;
musicOn = false;
}
@ -326,7 +316,7 @@ struct MusicManager
ALint count;
alGetSourcei(sID, AL_BUFFERS_PROCESSED, &count);
if(checkALError() != AL_NO_ERROR) return false;
if(checkALError("in isPlaying()")) return false;
for(int i = 0;i < count;i++)
{
@ -337,7 +327,7 @@ struct MusicManager
{
ALint state;
alGetSourcei(sID, AL_SOURCE_STATE, &state);
if(checkALError() != AL_NO_ERROR || state == AL_STOPPED)
if(checkALError() || state == AL_STOPPED)
return false;
}
break;

@ -119,7 +119,7 @@ struct SoundFile
{
alGenBuffers(1, &bID);
alBufferData(bID, fmt, outData.ptr, total, rate);
if(checkALError() != AL_NO_ERROR)
if(checkALError())
{
writefln("Unable to load sound %s", file);
alDeleteBuffers(1, &bID);
@ -143,11 +143,11 @@ struct SoundFile
SoundInstance si;
si.owner = this;
alGenSources(1, &si.inst);
if(checkALError() != AL_NO_ERROR || !si.inst)
if(checkALError() || !si.inst)
fail("Failed to instantiate sound resource");
alSourcei(si.inst, AL_BUFFER, cast(ALint)bID);
if(checkALError() != AL_NO_ERROR)
if(checkALError())
{
alDeleteSources(1, &si.inst);
fail("Failed to load sound resource");
@ -177,6 +177,7 @@ struct SoundFile
struct SoundInstance
{
ALuint inst;
ALfloat volume;
SoundFile *owner;
// Return this instance to the owner
@ -190,14 +191,14 @@ struct SoundInstance
void play()
{
alSourcePlay(inst);
checkALError();
checkALError("playing sound instance");
}
// Go buy a cookie
void stop()
{
alSourceStop(inst);
checkALError();
checkALError("stopping sound instance");
}
// Set parameters such as max volume and range
@ -208,12 +209,13 @@ struct SoundInstance
}
body
{
alSourcef(inst, AL_GAIN, volume);
this.volume = volume;
alSourcef(inst, AL_GAIN, 0);
alSourcef(inst, AL_REFERENCE_DISTANCE, minRange);
alSourcef(inst, AL_MAX_DISTANCE, maxRange);
alSourcei(inst, AL_LOOPING, repeat ? AL_TRUE : AL_FALSE);
alSourcePlay(inst);
checkALError();
checkALError("setting sound parameters");
}
// Set 3D position of sounds. Need to convert from app's world coords to
@ -221,7 +223,31 @@ struct SoundInstance
void setPos(float x, float y, float z)
{
alSource3f(inst, AL_POSITION, x, z, -y);
checkALError();
checkALError("setting sound position");
}
// TODO: This should probably be merged in setPos. All active sounds
// should respecify their position after the listener does, which would
// be ideal for keeping moving sounds moving while handling distance
// culling for moving and stationary sounds
void updateSound()
{
ALfloat lp[3];
ALfloat p[3];
ALfloat dist;
alGetSourcef(inst, AL_MAX_DISTANCE, &dist);
alGetSourcefv(inst, AL_POSITION, p.ptr);
alGetListenerfv(AL_POSITION, lp.ptr);
if(!checkALError("updating sound position"))
{
p[0] -= lp[0];
p[1] -= lp[1];
p[2] -= lp[2];
if((p[0]*p[0] + p[1]*p[1] + p[2]*p[2]) > dist*dist)
alSourcef(inst, AL_GAIN, 0);
else
alSourcef(inst, AL_GAIN, volume);
}
}
static void setPlayerPos(float x, float y, float z,
@ -237,6 +263,6 @@ struct SoundInstance
orient[5] =-upy;
alListener3f(AL_POSITION, x, z, -y);
alListenerfv(AL_ORIENTATION, orient.ptr);
checkALError();
checkALError("setting player position");
}
}

Loading…
Cancel
Save