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:
parent
9adf1e8461
commit
d57051375d
1 changed files with 160 additions and 6 deletions
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue