1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-01-31 21:45:33 +00:00

Implement non-streaming sounds with OpenAL

This commit is contained in:
Chris Robinson 2012-03-17 09:15:47 -07:00
parent 9adf1e8461
commit d57051375d

View file

@ -47,6 +47,32 @@ static ALenum getALFormat(Sound_Decoder::ChannelConfig chans, Sound_Decoder::Sam
}
ALuint LoadBuffer(std::auto_ptr<Sound_Decoder> decoder)
{
int srate;
Sound_Decoder::ChannelConfig chans;
Sound_Decoder::SampleType type;
ALenum format;
decoder->GetInfo(&srate, &chans, &type);
format = getALFormat(chans, type);
std::vector<char> data(32768);
size_t got, total = 0;
while((got=decoder->Read(&data[total], data.size()-total)) > 0)
{
total += got;
data.resize(total*2);
}
data.resize(total);
ALuint buf;
alGenBuffers(1, &buf);
alBufferData(buf, format, &data[0], total, srate);
return buf;
}
class OpenAL_SoundStream : public Sound
{
// This should be something sane, like 4, but currently cell loads tend to
@ -71,6 +97,21 @@ public:
virtual bool isPlaying();
};
class OpenAL_Sound : public Sound
{
public:
ALuint Source;
ALuint Buffer;
OpenAL_Sound(ALuint src, ALuint buf);
virtual ~OpenAL_Sound();
virtual void Play();
virtual void Stop();
virtual bool isPlaying();
};
OpenAL_SoundStream::OpenAL_SoundStream(std::auto_ptr<Sound_Decoder> decoder)
: Decoder(decoder)
{
@ -190,6 +231,38 @@ bool OpenAL_SoundStream::isPlaying()
}
OpenAL_Sound::OpenAL_Sound(ALuint src, ALuint buf)
: Source(src), Buffer(buf)
{
}
OpenAL_Sound::~OpenAL_Sound()
{
alDeleteSources(1, &Source);
alDeleteBuffers(1, &Buffer);
alGetError();
}
void OpenAL_Sound::Play()
{
}
void OpenAL_Sound::Stop()
{
alSourceStop(Source);
throwALerror();
}
bool OpenAL_Sound::isPlaying()
{
ALint state;
alGetSourcei(Source, AL_SOURCE_STATE, &state);
throwALerror();
return state==AL_PLAYING;
}
bool OpenAL_Output::Initialize(const std::string &devname)
{
if(Context)
@ -233,16 +306,97 @@ void OpenAL_Output::Deinitialize()
Sound* OpenAL_Output::PlaySound(const std::string &fname, std::auto_ptr<Sound_Decoder> decoder,
float volume, float pitch, bool loop)
{
fail("PlaySound not yet supported");
return NULL;
throwALerror();
decoder->Open(fname);
ALuint src=0, buf=0;
try
{
buf = LoadBuffer(decoder);
alGenSources(1, &src);
throwALerror();
}
catch(std::exception &e)
{
if(alIsSource(buf))
alDeleteSources(1, &src);
if(alIsBuffer(buf))
alDeleteBuffers(1, &buf);
alGetError();
throw;
}
std::auto_ptr<OpenAL_Sound> sound(new OpenAL_Sound(src, buf));
alSource3f(src, AL_POSITION, 0.0f, 0.0f, 0.0f);
alSource3f(src, AL_DIRECTION, 0.0f, 0.0f, 0.0f);
alSource3f(src, AL_VELOCITY, 0.0f, 0.0f, 0.0f);
alSourcef(src, AL_REFERENCE_DISTANCE, 1.0f);
alSourcef(src, AL_MAX_DISTANCE, 1000.0f);
alSourcef(src, AL_ROLLOFF_FACTOR, 0.0f);
alSourcef(src, AL_GAIN, volume);
alSourcef(src, AL_PITCH, pitch);
alSourcei(src, AL_SOURCE_RELATIVE, AL_TRUE);
alSourcei(src, AL_LOOPING, (loop?AL_TRUE:AL_FALSE));
throwALerror();
alSourcei(src, AL_BUFFER, buf);
alSourcePlay(src);
throwALerror();
return sound.release();
}
Sound* OpenAL_Output::PlaySound3D(const std::string &fname, std::auto_ptr<Sound_Decoder> decoder,
MWWorld::Ptr ptr, float volume, float pitch,
float min, float max, bool loop)
MWWorld::Ptr ptr, float volume, float pitch,
float min, float max, bool loop)
{
fail("PlaySound3D not yet supported");
return NULL;
throwALerror();
decoder->Open(fname);
ALuint src=0, buf=0;
try
{
buf = LoadBuffer(decoder);
alGenSources(1, &src);
throwALerror();
}
catch(std::exception &e)
{
if(alIsSource(buf))
alDeleteSources(1, &src);
if(alIsBuffer(buf))
alDeleteBuffers(1, &buf);
alGetError();
throw;
}
std::auto_ptr<OpenAL_Sound> sound(new OpenAL_Sound(src, buf));
const float *pos = ptr.getCellRef().pos.pos;
alSource3f(src, AL_POSITION, pos[0], pos[2], -pos[1]);
alSource3f(src, AL_DIRECTION, 0.0f, 0.0f, 0.0f);
alSource3f(src, AL_VELOCITY, 0.0f, 0.0f, 0.0f);
alSourcef(src, AL_REFERENCE_DISTANCE, min);
alSourcef(src, AL_MAX_DISTANCE, max);
alSourcef(src, AL_ROLLOFF_FACTOR, 1.0f);
alSourcef(src, AL_GAIN, volume);
alSourcef(src, AL_PITCH, pitch);
alSourcei(src, AL_SOURCE_RELATIVE, AL_FALSE);
alSourcei(src, AL_LOOPING, (loop?AL_TRUE:AL_FALSE));
throwALerror();
alSourcei(src, AL_BUFFER, buf);
alSourcePlay(src);
throwALerror();
return sound.release();
}