Add a method to retrieve the play position of a SoundStream

This commit is contained in:
Chris Robinson 2022-09-27 21:58:37 -07:00 committed by Christoph Oelckers
parent c808aad595
commit 78f40fe99c
2 changed files with 39 additions and 3 deletions

View file

@ -35,6 +35,7 @@
#ifndef __I_SOUND__
#define __I_SOUND__
#include <chrono>
#include <vector>
#include "i_soundinternal.h"
#include "zstring.h"
@ -62,7 +63,7 @@ enum ECodecType
class SoundStream
{
public:
virtual ~SoundStream () {}
virtual ~SoundStream() = default;
enum
{ // For CreateStream
@ -75,11 +76,18 @@ public:
Loop = 16
};
struct Position {
uint64_t samplesplayed;
std::chrono::nanoseconds latency;
};
virtual bool Play(bool looping, float volume) = 0;
virtual void Stop() = 0;
virtual void SetVolume(float volume) = 0;
virtual bool SetPaused(bool paused) = 0;
virtual bool IsEnded() = 0;
// Be aware this can be called during the callback invocation after Play is called.
virtual Position GetPlayPosition() = 0;
virtual FString GetStats();
};

View file

@ -183,6 +183,8 @@ class OpenALSoundStream : public SoundStream
std::atomic<bool> Playing;
//bool Looping;
ALfloat Volume;
uint64_t Offset = 0;
std::mutex Mutex;
bool SetupSource()
{
@ -263,6 +265,7 @@ public:
return true;
/* Clear the buffer queue, then fill and queue each buffer */
Offset = 0;
alSourcei(Source, AL_BUFFER, 0);
for(int i = 0;i < BufferCount;i++)
{
@ -297,6 +300,7 @@ public:
alSourcei(Source, AL_BUFFER, 0);
getALError();
Offset = 0;
Playing.store(false);
}
@ -326,6 +330,26 @@ public:
return !Playing.load();
}
Position GetPlayPosition() override
{
using namespace std::chrono;
std::lock_guard _{Mutex};
// TODO: Get latency using AL_SOFT_source_latency
ALint state{}, offset{}, queued{};
alGetSourcei(Source, AL_BUFFERS_QUEUED, &queued);
alGetSourcei(Source, AL_SAMPLE_OFFSET, &offset);
alGetSourcei(Source, AL_SOURCE_STATE, &state);
// If the source is stopped, there was an underrun, so the play position is
// the end of the queue.
if(state == AL_STOPPED)
return Position{Offset + queued*(Data.Size()/FrameSize), nanoseconds{0}};
// The offset is otherwise valid as long as the source has been started.
if(state != AL_INITIAL)
return Position{Offset + offset, nanoseconds{0}};
return Position{0, nanoseconds{0}};
}
virtual FString GetStats()
{
FString stats;
@ -386,8 +410,12 @@ public:
// Unqueue the oldest buffer, fill it with more data, and queue it
// on the end
alSourceUnqueueBuffers(Source, 1, &bufid);
processed--;
{
std::lock_guard _{Mutex};
alSourceUnqueueBuffers(Source, 1, &bufid);
Offset += Data.Size() / FrameSize;
processed--;
}
if(Callback(this, &Data[0], Data.Size(), UserData))
{