aboutsummaryrefslogtreecommitdiffstats
path: root/alc
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2020-02-17 17:13:00 -0800
committerChris Robinson <[email protected]>2020-02-17 17:13:25 -0800
commit3122c3b4a109b7d6e288bdde055fc4bbae5517bc (patch)
treeb2eb3a251a243d3a5f9a7566c343bc614c9ff8cc /alc
parentc8dfd248185359d86410340741122943524ed10b (diff)
Handle running the buffer callback in the voice
Diffstat (limited to 'alc')
-rw-r--r--alc/voice.cpp76
-rw-r--r--alc/voice.h19
2 files changed, 77 insertions, 18 deletions
diff --git a/alc/voice.cpp b/alc/voice.cpp
index 752f13a9..19b4da2d 100644
--- a/alc/voice.cpp
+++ b/alc/voice.cpp
@@ -387,6 +387,23 @@ ALfloat *LoadBufferStatic(ALbufferlistitem *BufferListItem, ALbufferlistitem *&B
return SrcBuffer.begin();
}
+ALfloat *LoadBufferCallback(ALbufferlistitem *BufferListItem, const size_t NumChannels,
+ const size_t SampleSize, const size_t chan, size_t NumCallbackSamples,
+ al::span<ALfloat> SrcBuffer)
+{
+ const ALbuffer *Buffer{BufferListItem->mBuffer};
+
+ /* Load what's left to play from the buffer */
+ const size_t DataRem{minz(SrcBuffer.size(), NumCallbackSamples)};
+
+ const al::byte *Data{Buffer->mData.data() + chan*SampleSize};
+
+ LoadSamples(SrcBuffer.data(), Data, NumChannels, Buffer->mFmtType, DataRem);
+ SrcBuffer = SrcBuffer.subspan(DataRem);
+
+ return SrcBuffer.begin();
+}
+
ALfloat *LoadBufferQueue(ALbufferlistitem *BufferListItem, ALbufferlistitem *BufferLoopItem,
const size_t NumChannels, const size_t SampleSize, const size_t chan, size_t DataPosInt,
al::span<ALfloat> SrcBuffer)
@@ -531,7 +548,6 @@ void ALvoice::mix(const State vstate, ALCcontext *Context, const ALuint SamplesT
ASSUME(SamplesToDo > 0);
/* Get voice info */
- const ALuint vtype{mFlags&VOICE_TYPE_MASK};
ALuint DataPosInt{mPosition.load(std::memory_order_relaxed)};
ALuint DataPosFrac{mPositionFrac.load(std::memory_order_relaxed)};
ALbufferlistitem *BufferListItem{mCurrentBuffer.load(std::memory_order_relaxed)};
@@ -552,6 +568,7 @@ void ALvoice::mix(const State vstate, ALCcontext *Context, const ALuint SamplesT
ASSUME(NumChannels > 0);
ASSUME(SampleSize > 0);
ASSUME(increment > 0);
+ const auto FrameSize = size_t{NumChannels} * SampleSize;
ALCdevice *Device{Context->mDevice.get()};
const ALuint NumSends{Device->NumAuxSends};
@@ -634,6 +651,32 @@ void ALvoice::mix(const State vstate, ALCcontext *Context, const ALuint SamplesT
DstBufferSize &= ~3u;
}
+ if((mFlags&(VOICE_IS_CALLBACK|VOICE_CALLBACK_STOPPED)) == VOICE_IS_CALLBACK
+ && BufferListItem)
+ {
+ ALbuffer *buffer{BufferListItem->mBuffer};
+
+ /* Exclude resampler pre-padding from the needed size. */
+ const ALuint toLoad{SrcBufferSize - (MAX_RESAMPLER_PADDING>>1)};
+ if(toLoad > mNumCallbackSamples)
+ {
+ const size_t byteOffset{mNumCallbackSamples*FrameSize};
+ const size_t needBytes{toLoad*FrameSize - byteOffset};
+
+ const ALsizei gotBytes{buffer->Callback(buffer->UserData,
+ &buffer->mData[byteOffset], static_cast<ALsizei>(needBytes))};
+ if(gotBytes < 1)
+ mFlags |= VOICE_CALLBACK_STOPPED;
+ else if(static_cast<ALuint>(gotBytes) < needBytes)
+ {
+ mFlags |= VOICE_CALLBACK_STOPPED;
+ mNumCallbackSamples += static_cast<ALuint>(gotBytes) / FrameSize;
+ }
+ else
+ mNumCallbackSamples = toLoad;
+ }
+ }
+
ASSUME(DstBufferSize > 0);
for(ALuint chan{0};chan < NumChannels;chan++)
{
@@ -649,13 +692,12 @@ void ALvoice::mix(const State vstate, ALCcontext *Context, const ALuint SamplesT
if UNLIKELY(!BufferListItem)
srciter = std::copy(chandata.mPrevSamples.begin()+(MAX_RESAMPLER_PADDING>>1),
chandata.mPrevSamples.end(), srciter);
- else if(vtype == VOICE_IS_STATIC)
+ else if((mFlags&VOICE_IS_STATIC))
srciter = LoadBufferStatic(BufferListItem, BufferLoopItem, NumChannels,
SampleSize, chan, DataPosInt, {srciter, SrcData.end()});
- else if(vtype == VOICE_IS_CALLBACK)
- {
- /* Not Yet Implemented. */
- }
+ else if((mFlags&VOICE_IS_CALLBACK))
+ srciter = LoadBufferCallback(BufferListItem, NumChannels, SampleSize, chan,
+ mNumCallbackSamples, {srciter, SrcData.end()});
else
srciter = LoadBufferQueue(BufferListItem, BufferLoopItem, NumChannels,
SampleSize, chan, DataPosInt, {srciter, SrcData.end()});
@@ -739,7 +781,8 @@ void ALvoice::mix(const State vstate, ALCcontext *Context, const ALuint SamplesT
}
/* Update positions */
DataPosFrac += increment*DstBufferSize;
- DataPosInt += DataPosFrac>>FRACTIONBITS;
+ const ALuint SrcSamplesDone{DataPosFrac>>FRACTIONBITS};
+ DataPosInt += SrcSamplesDone;
DataPosFrac &= FRACTIONMASK;
OutPos += DstBufferSize;
@@ -749,7 +792,7 @@ void ALvoice::mix(const State vstate, ALCcontext *Context, const ALuint SamplesT
{
/* Do nothing extra when there's no buffers. */
}
- else if(vtype == VOICE_IS_STATIC)
+ else if((mFlags&VOICE_IS_STATIC))
{
if(BufferLoopItem)
{
@@ -773,9 +816,22 @@ void ALvoice::mix(const State vstate, ALCcontext *Context, const ALuint SamplesT
}
}
}
- else if(vtype == VOICE_IS_CALLBACK)
+ else if((mFlags&VOICE_IS_CALLBACK))
{
- /* Do nothing extra for callback buffers. */
+ ALbuffer *buffer{BufferListItem->mBuffer};
+ if(SrcSamplesDone < mNumCallbackSamples)
+ {
+ const size_t byteOffset{SrcSamplesDone*FrameSize};
+ const size_t byteEnd{mNumCallbackSamples*FrameSize};
+ std::copy(buffer->mData.data()+byteOffset, buffer->mData.data()+byteEnd,
+ buffer->mData.data());
+ mNumCallbackSamples -= SrcSamplesDone;
+ }
+ else
+ {
+ BufferListItem = nullptr;
+ mNumCallbackSamples = 0;
+ }
}
else
{
diff --git a/alc/voice.h b/alc/voice.h
index a5b6fac5..73344271 100644
--- a/alc/voice.h
+++ b/alc/voice.h
@@ -180,12 +180,13 @@ struct ALvoiceProps : public ALvoicePropsBase {
DEF_NEWDEL(ALvoiceProps)
};
-#define VOICE_IS_STATIC (1u<<0)
-#define VOICE_IS_CALLBACK (1u<<1)
-#define VOICE_IS_AMBISONIC (1u<<2) /* Voice needs HF scaling for ambisonic upsampling. */
-#define VOICE_IS_FADING (1u<<3) /* Fading sources use gain stepping for smooth transitions. */
-#define VOICE_HAS_HRTF (1u<<4)
-#define VOICE_HAS_NFC (1u<<5)
+#define VOICE_IS_STATIC (1u<<0)
+#define VOICE_IS_CALLBACK (1u<<1)
+#define VOICE_IS_AMBISONIC (1u<<2) /* Voice needs HF scaling for ambisonic upsampling. */
+#define VOICE_CALLBACK_STOPPED (1u<<3)
+#define VOICE_IS_FADING (1u<<4) /* Fading sources use gain stepping for smooth transitions. */
+#define VOICE_HAS_HRTF (1u<<5)
+#define VOICE_HAS_NFC (1u<<6)
#define VOICE_TYPE_MASK (VOICE_IS_STATIC | VOICE_IS_CALLBACK)
@@ -229,13 +230,14 @@ struct ALvoice {
ALuint mAmbiOrder;
/** Current target parameters used for mixing. */
- ALuint mStep;
+ ALuint mStep{0};
ResamplerFunc mResampler;
InterpState mResampleState;
- ALuint mFlags;
+ ALuint mFlags{};
+ ALuint mNumCallbackSamples{0};
struct TargetData {
int FilterType;
@@ -295,6 +297,7 @@ struct ALvoice {
mResampleState = rhs.mResampleState;
mFlags = rhs.mFlags;
+ mNumCallbackSamples = rhs.mNumCallbackSamples;
mDirect = rhs.mDirect;
mSend = rhs.mSend;