1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-01-31 23:15:41 +00:00

Implement getTimeOffset for OpenAL_SoundStream

This commit is contained in:
Chris Robinson 2012-12-12 23:13:35 -08:00
parent 86bf6388c6
commit 1571243ef0

View file

@ -65,6 +65,18 @@ static ALenum getALFormat(ChannelConfig chans, SampleType type)
return AL_NONE; return AL_NONE;
} }
static ALint getBufferSampleCount(ALuint buf)
{
ALint size, bits, channels;
alGetBufferi(buf, AL_SIZE, &size);
alGetBufferi(buf, AL_BITS, &bits);
alGetBufferi(buf, AL_CHANNELS, &channels);
throwALerror();
return size / channels * 8 / bits;
}
// //
// A streaming OpenAL sound. // A streaming OpenAL sound.
// //
@ -82,6 +94,9 @@ class OpenAL_SoundStream : public Sound
ALsizei mSampleRate; ALsizei mSampleRate;
ALuint mBufferSize; ALuint mBufferSize;
ALuint mSamplesTotal;
ALuint mSamplesQueued;
DecoderPtr mDecoder; DecoderPtr mDecoder;
volatile bool mIsFinished; volatile bool mIsFinished;
@ -172,7 +187,8 @@ private:
OpenAL_SoundStream::OpenAL_SoundStream(OpenAL_Output &output, ALuint src, DecoderPtr decoder) OpenAL_SoundStream::OpenAL_SoundStream(OpenAL_Output &output, ALuint src, DecoderPtr decoder)
: mOutput(output), mSource(src), mDecoder(decoder), mIsFinished(true) : mOutput(output), mSource(src), mSamplesTotal(0), mSamplesQueued(0),
mDecoder(decoder), mIsFinished(true)
{ {
throwALerror(); throwALerror();
@ -215,16 +231,19 @@ OpenAL_SoundStream::~OpenAL_SoundStream()
void OpenAL_SoundStream::play() void OpenAL_SoundStream::play()
{ {
std::vector<char> data(mBufferSize); std::vector<char> data(mBufferSize);
ALuint count = 0;
alSourceStop(mSource); alSourceStop(mSource);
alSourcei(mSource, AL_BUFFER, 0); alSourcei(mSource, AL_BUFFER, 0);
throwALerror(); throwALerror();
mSamplesQueued = 0;
for(ALuint i = 0;i < sNumBuffers;i++) for(ALuint i = 0;i < sNumBuffers;i++)
{ {
size_t got; size_t got;
got = mDecoder->read(&data[0], data.size()); got = mDecoder->read(&data[0], data.size());
alBufferData(mBuffers[i], mFormat, &data[0], got, mSampleRate); alBufferData(mBuffers[i], mFormat, &data[0], got, mSampleRate);
count += getBufferSampleCount(mBuffers[i]);
} }
throwALerror(); throwALerror();
@ -232,6 +251,9 @@ void OpenAL_SoundStream::play()
alSourcePlay(mSource); alSourcePlay(mSource);
throwALerror(); throwALerror();
mSamplesTotal += count;
mSamplesQueued = count;
mIsFinished = false; mIsFinished = false;
mOutput.mStreamThread->add(this); mOutput.mStreamThread->add(this);
} }
@ -244,8 +266,10 @@ void OpenAL_SoundStream::stop()
alSourceStop(mSource); alSourceStop(mSource);
alSourcei(mSource, AL_BUFFER, 0); alSourcei(mSource, AL_BUFFER, 0);
throwALerror(); throwALerror();
mSamplesQueued = 0;
mDecoder->rewind(); mDecoder->rewind();
mSamplesTotal = 0;
} }
bool OpenAL_SoundStream::isPlaying() bool OpenAL_SoundStream::isPlaying()
@ -262,7 +286,21 @@ bool OpenAL_SoundStream::isPlaying()
double OpenAL_SoundStream::getTimeOffset() double OpenAL_SoundStream::getTimeOffset()
{ {
return 0.0; ALint state = AL_STOPPED;
ALfloat offset = 0.0f;
double t;
mOutput.mStreamThread->mMutex.lock();
alGetSourcef(mSource, AL_SEC_OFFSET, &offset);
alGetSourcei(mSource, AL_SOURCE_STATE, &state);
if(state == AL_PLAYING || state == AL_PAUSED)
t = (double)(mSamplesTotal - mSamplesQueued)/(double)mSampleRate + offset;
else
t = (double)mSamplesTotal / (double)mSampleRate;
mOutput.mStreamThread->mMutex.unlock();
throwALerror();
return t;
} }
void OpenAL_SoundStream::update() void OpenAL_SoundStream::update()
@ -285,52 +323,64 @@ void OpenAL_SoundStream::update()
bool OpenAL_SoundStream::process() bool OpenAL_SoundStream::process()
{ {
bool finished = mIsFinished; try {
ALint processed, state; bool finished = mIsFinished;
ALint samples_unqueued = 0;
ALint samples_queued = 0;
ALint processed, state;
alGetSourcei(mSource, AL_SOURCE_STATE, &state); alGetSourcei(mSource, AL_SOURCE_STATE, &state);
alGetSourcei(mSource, AL_BUFFERS_PROCESSED, &processed); alGetSourcei(mSource, AL_BUFFERS_PROCESSED, &processed);
throwALerror();
if(processed > 0)
{
std::vector<char> data(mBufferSize);
do {
ALuint bufid;
size_t got;
alSourceUnqueueBuffers(mSource, 1, &bufid);
processed--;
if(finished)
continue;
got = mDecoder->read(&data[0], data.size());
finished = (got < data.size());
if(got > 0)
{
alBufferData(bufid, mFormat, &data[0], got, mSampleRate);
alSourceQueueBuffers(mSource, 1, &bufid);
}
} while(processed > 0);
throwALerror(); throwALerror();
}
if(state != AL_PLAYING && state != AL_PAUSED) if(processed > 0)
{
ALint queued;
alGetSourcei(mSource, AL_BUFFERS_QUEUED, &queued);
throwALerror();
if(queued > 0)
{ {
alSourcePlay(mSource); std::vector<char> data(mBufferSize);
do {
ALuint bufid = 0;
size_t got;
alSourceUnqueueBuffers(mSource, 1, &bufid);
samples_unqueued += getBufferSampleCount(bufid);
processed--;
if(finished)
continue;
got = mDecoder->read(&data[0], data.size());
finished = (got < data.size());
if(got > 0)
{
alBufferData(bufid, mFormat, &data[0], got, mSampleRate);
alSourceQueueBuffers(mSource, 1, &bufid);
samples_queued += getBufferSampleCount(bufid);
}
} while(processed > 0);
throwALerror(); throwALerror();
} }
}
mIsFinished = finished; if(state != AL_PLAYING && state != AL_PAUSED)
return !finished; {
ALint queued = 0;
alGetSourcei(mSource, AL_BUFFERS_QUEUED, &queued);
if(queued > 0)
alSourcePlay(mSource);
throwALerror();
}
mSamplesQueued -= samples_unqueued;
mSamplesQueued += samples_queued;
mSamplesTotal += samples_queued;
mIsFinished = finished;
}
catch(std::exception &e) {
std::cout<< "Error updating stream \""<<mDecoder->getName()<<"\"" <<std::endl;
mSamplesQueued = 0;
mSamplesTotal = 0;
mIsFinished = true;
}
return !mIsFinished;
} }
// //