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__ #ifndef __I_SOUND__
#define __I_SOUND__ #define __I_SOUND__
#include <chrono>
#include <vector> #include <vector>
#include "i_soundinternal.h" #include "i_soundinternal.h"
#include "zstring.h" #include "zstring.h"
@ -62,7 +63,7 @@ enum ECodecType
class SoundStream class SoundStream
{ {
public: public:
virtual ~SoundStream () {} virtual ~SoundStream() = default;
enum enum
{ // For CreateStream { // For CreateStream
@ -75,11 +76,18 @@ public:
Loop = 16 Loop = 16
}; };
struct Position {
uint64_t samplesplayed;
std::chrono::nanoseconds latency;
};
virtual bool Play(bool looping, float volume) = 0; virtual bool Play(bool looping, float volume) = 0;
virtual void Stop() = 0; virtual void Stop() = 0;
virtual void SetVolume(float volume) = 0; virtual void SetVolume(float volume) = 0;
virtual bool SetPaused(bool paused) = 0; virtual bool SetPaused(bool paused) = 0;
virtual bool IsEnded() = 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(); virtual FString GetStats();
}; };

View file

@ -183,6 +183,8 @@ class OpenALSoundStream : public SoundStream
std::atomic<bool> Playing; std::atomic<bool> Playing;
//bool Looping; //bool Looping;
ALfloat Volume; ALfloat Volume;
uint64_t Offset = 0;
std::mutex Mutex;
bool SetupSource() bool SetupSource()
{ {
@ -263,6 +265,7 @@ public:
return true; return true;
/* Clear the buffer queue, then fill and queue each buffer */ /* Clear the buffer queue, then fill and queue each buffer */
Offset = 0;
alSourcei(Source, AL_BUFFER, 0); alSourcei(Source, AL_BUFFER, 0);
for(int i = 0;i < BufferCount;i++) for(int i = 0;i < BufferCount;i++)
{ {
@ -297,6 +300,7 @@ public:
alSourcei(Source, AL_BUFFER, 0); alSourcei(Source, AL_BUFFER, 0);
getALError(); getALError();
Offset = 0;
Playing.store(false); Playing.store(false);
} }
@ -326,6 +330,26 @@ public:
return !Playing.load(); 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() virtual FString GetStats()
{ {
FString stats; FString stats;
@ -386,8 +410,12 @@ public:
// Unqueue the oldest buffer, fill it with more data, and queue it // Unqueue the oldest buffer, fill it with more data, and queue it
// on the end // on the end
{
std::lock_guard _{Mutex};
alSourceUnqueueBuffers(Source, 1, &bufid); alSourceUnqueueBuffers(Source, 1, &bufid);
Offset += Data.Size() / FrameSize;
processed--; processed--;
}
if(Callback(this, &Data[0], Data.Size(), UserData)) if(Callback(this, &Data[0], Data.Size(), UserData))
{ {