aboutsummaryrefslogtreecommitdiffstats
path: root/al
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2020-04-04 01:52:29 -0700
committerChris Robinson <[email protected]>2020-04-04 01:52:29 -0700
commitfc906c97f52fd13549dfdfae229d0dc6d60a2865 (patch)
tree278b33097cd082f85442fe785579e6b78969e652 /al
parent902f5a0dd267e0849e93e863a24a0a350d1696f9 (diff)
Track a buffer's ambisonic order
Diffstat (limited to 'al')
-rw-r--r--al/buffer.cpp31
-rw-r--r--al/buffer.h6
-rw-r--r--al/source.cpp26
3 files changed, 42 insertions, 21 deletions
diff --git a/al/buffer.cpp b/al/buffer.cpp
index a84f56a6..4acd1158 100644
--- a/al/buffer.cpp
+++ b/al/buffer.cpp
@@ -273,8 +273,6 @@ ALuint ChannelsFromUserFmt(UserFmtChannels chans, ALuint ambiorder) noexcept
}
return 0;
}
-inline ALuint FrameSizeFromUserFmt(UserFmtChannels chans, UserFmtType type, ALuint ambiorder) noexcept
-{ return ChannelsFromUserFmt(chans, ambiorder) * BytesFromUserFmt(type); }
constexpr ALbitfieldSOFT INVALID_STORAGE_MASK{~unsigned(AL_MAP_READ_BIT_SOFT |
@@ -462,6 +460,9 @@ void LoadData(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq, ALuint size,
SETERR_RETURN(context, AL_INVALID_VALUE,, "Invalid unpack alignment %u for %s samples",
unpackalign, NameFromUserFmtType(SrcType));
+ const ALuint ambiorder{(DstChannels == FmtBFormat2D || DstChannels == FmtBFormat3D) ?
+ ALBuf->UnpackAmbiOrder : 0};
+
if((access&AL_PRESERVE_DATA_BIT_SOFT))
{
/* Can only preserve data with the same format and alignment. */
@@ -469,15 +470,17 @@ void LoadData(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq, ALuint size,
SETERR_RETURN(context, AL_INVALID_VALUE,, "Preserving data of mismatched format");
if UNLIKELY(ALBuf->OriginalAlign != align)
SETERR_RETURN(context, AL_INVALID_VALUE,, "Preserving data of mismatched alignment");
+ if(ALBuf->AmbiOrder != ambiorder)
+ SETERR_RETURN(context, AL_INVALID_VALUE,, "Preserving data of mismatched order");
}
/* Convert the input/source size in bytes to sample frames using the unpack
* block alignment.
*/
- const ALuint SrcByteAlign{
- (SrcType == UserFmtIMA4) ? ((align-1)/2 + 4) * ChannelsFromUserFmt(SrcChannels, 1) :
- (SrcType == UserFmtMSADPCM) ? ((align-2)/2 + 7) * ChannelsFromUserFmt(SrcChannels, 1) :
- (align * FrameSizeFromUserFmt(SrcChannels, SrcType, 1))};
+ const ALuint SrcByteAlign{ChannelsFromUserFmt(SrcChannels, ambiorder) *
+ ((SrcType == UserFmtIMA4) ? (align-1)/2 + 4 :
+ (SrcType == UserFmtMSADPCM) ? (align-2)/2 + 7 :
+ (align * BytesFromUserFmt(SrcType)))};
if UNLIKELY((size%SrcByteAlign) != 0)
SETERR_RETURN(context, AL_INVALID_VALUE,,
"Data size %d is not a multiple of frame size %d (%d unpack alignment)",
@@ -491,7 +494,7 @@ void LoadData(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq, ALuint size,
/* Convert the sample frames to the number of bytes needed for internal
* storage.
*/
- ALuint NumChannels{ChannelsFromFmt(DstChannels, 1)};
+ ALuint NumChannels{ChannelsFromFmt(DstChannels, ambiorder)};
ALuint FrameSize{NumChannels * BytesFromFmt(DstType)};
if UNLIKELY(frames > std::numeric_limits<size_t>::max()/FrameSize)
SETERR_RETURN(context, AL_OUT_OF_MEMORY,,
@@ -513,7 +516,7 @@ void LoadData(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq, ALuint size,
const size_t tocopy{minz(newdata.size(), ALBuf->mData.size())};
std::copy_n(ALBuf->mData.begin(), tocopy, newdata.begin());
}
- ALBuf->mData = std::move(newdata);
+ newdata.swap(ALBuf->mData);
}
if(SrcType == UserFmtIMA4)
@@ -546,6 +549,7 @@ void LoadData(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq, ALuint size,
ALBuf->mFmtChannels = DstChannels;
ALBuf->mFmtType = DstType;
ALBuf->Access = access;
+ ALBuf->AmbiOrder = ambiorder;
ALBuf->Callback = nullptr;
ALBuf->UserData = nullptr;
@@ -597,8 +601,11 @@ void PrepareCallback(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq,
if UNLIKELY(static_cast<long>(SrcType) != static_cast<long>(DstType))
SETERR_RETURN(context, AL_INVALID_ENUM,, "Unsupported callback format");
- ALBuf->mData = al::vector<al::byte,16>(FrameSizeFromFmt(DstChannels, DstType, 1) *
- size_t{BUFFERSIZE + (MAX_RESAMPLER_PADDING>>1)});
+ const ALuint ambiorder{(DstChannels == FmtBFormat2D || DstChannels == FmtBFormat3D) ?
+ ALBuf->UnpackAmbiOrder : 0};
+
+ al::vector<al::byte,16>(FrameSizeFromFmt(DstChannels, DstType, ambiorder) *
+ size_t{BUFFERSIZE + (MAX_RESAMPLER_PADDING>>1)}).swap(ALBuf->mData);
ALBuf->Callback = callback;
ALBuf->UserData = userptr;
@@ -611,6 +618,7 @@ void PrepareCallback(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq,
ALBuf->mFmtChannels = DstChannels;
ALBuf->mFmtType = DstType;
ALBuf->Access = 0;
+ ALBuf->AmbiOrder = ambiorder;
ALBuf->SampleLen = 0;
ALBuf->LoopStart = 0;
@@ -976,6 +984,9 @@ START_API_FUNC
context->setError(AL_INVALID_VALUE,
"Unpacking data with alignment %u does not match original alignment %u", align,
albuf->OriginalAlign);
+ else if UNLIKELY((albuf->mFmtChannels == FmtBFormat2D || albuf->mFmtChannels == FmtBFormat3D)
+ && albuf->UnpackAmbiOrder != albuf->AmbiOrder)
+ context->setError(AL_INVALID_VALUE, "Unpacking data with mismatched ambisonic order");
else if UNLIKELY(albuf->MappedAccess != 0)
context->setError(AL_INVALID_OPERATION, "Unpacking data into mapped buffer %u", buffer);
else
diff --git a/al/buffer.h b/al/buffer.h
index 44ada667..2e98e927 100644
--- a/al/buffer.h
+++ b/al/buffer.h
@@ -79,6 +79,8 @@ struct ALbuffer {
ALenum AmbiLayout{AL_FUMA_SOFT};
ALenum AmbiScaling{AL_FUMA_SOFT};
+ /* AmbiOrder is only updated when loading new data. */
+ ALuint AmbiOrder{0};
LPALBUFFERCALLBACKTYPESOFT Callback{nullptr};
void *UserData{nullptr};
@@ -88,6 +90,7 @@ struct ALbuffer {
ALuint UnpackAlign{0};
ALuint PackAlign{0};
+ ALuint UnpackAmbiOrder{1};
ALbitfieldSOFT MappedAccess{0u};
ALsizei MappedOffset{0};
@@ -100,7 +103,8 @@ struct ALbuffer {
ALuint id{0};
inline ALuint bytesFromFmt() const noexcept { return BytesFromFmt(mFmtType); }
- inline ALuint channelsFromFmt() const noexcept { return ChannelsFromFmt(mFmtChannels, 1); }
+ inline ALuint channelsFromFmt() const noexcept
+ { return ChannelsFromFmt(mFmtChannels, AmbiOrder); }
inline ALuint frameSizeFromFmt() const noexcept { return channelsFromFmt() * bytesFromFmt(); }
DISABLE_ALLOC()
diff --git a/al/source.cpp b/al/source.cpp
index 57ad151d..7d32de34 100644
--- a/al/source.cpp
+++ b/al/source.cpp
@@ -447,7 +447,7 @@ void InitVoice(Voice *voice, ALsource *source, ALbufferlistitem *BufferList, ALC
voice->mSampleSize = buffer->bytesFromFmt();
voice->mAmbiLayout = static_cast<AmbiLayout>(buffer->AmbiLayout);
voice->mAmbiScaling = static_cast<AmbiNorm>(buffer->AmbiScaling);
- voice->mAmbiOrder = 1;
+ voice->mAmbiOrder = buffer->AmbiOrder;
if(buffer->Callback) voice->mFlags |= VOICE_IS_CALLBACK;
else if(source->SourceType == AL_STATIC) voice->mFlags |= VOICE_IS_STATIC;
@@ -466,8 +466,7 @@ void InitVoice(Voice *voice, ALsource *source, ALbufferlistitem *BufferList, ALC
/* Don't need to set the VOICE_IS_AMBISONIC flag if the device is not
* higher order than the voice. No HF scaling is necessary to mix it.
*/
- if((voice->mFmtChannels == FmtBFormat2D || voice->mFmtChannels == FmtBFormat3D)
- && device->mAmbiOrder > voice->mAmbiOrder)
+ if(voice->mAmbiOrder && device->mAmbiOrder > voice->mAmbiOrder)
{
const uint8_t *OrderFromChan{(voice->mFmtChannels == FmtBFormat2D) ?
AmbiIndex::OrderFrom2DChannel.data() :
@@ -3203,6 +3202,7 @@ START_API_FUNC
BufferList = nullptr;
for(ALsizei i{0};i < nb;i++)
{
+ bool fmt_mismatch{false};
ALbuffer *buffer{nullptr};
if(buffers[i] && (buffer=LookupBuffer(device, buffers[i])) == nullptr)
{
@@ -3242,13 +3242,19 @@ START_API_FUNC
if(BufferFmt == nullptr)
BufferFmt = buffer;
- else if(BufferFmt->Frequency != buffer->Frequency ||
- BufferFmt->mFmtChannels != buffer->mFmtChannels ||
- ((BufferFmt->mFmtChannels == FmtBFormat2D ||
- BufferFmt->mFmtChannels == FmtBFormat3D) &&
- (BufferFmt->AmbiLayout != buffer->AmbiLayout ||
- BufferFmt->AmbiScaling != buffer->AmbiScaling)) ||
- BufferFmt->OriginalType != buffer->OriginalType)
+ else
+ {
+ fmt_mismatch |= BufferFmt->Frequency != buffer->Frequency;
+ fmt_mismatch |= BufferFmt->mFmtChannels != buffer->mFmtChannels;
+ if(BufferFmt->mFmtChannels == FmtBFormat2D || BufferFmt->mFmtChannels == FmtBFormat3D)
+ {
+ fmt_mismatch |= BufferFmt->AmbiLayout != buffer->AmbiLayout;
+ fmt_mismatch |= BufferFmt->AmbiScaling != buffer->AmbiScaling;
+ }
+ fmt_mismatch |= BufferFmt->AmbiOrder != buffer->AmbiOrder;
+ fmt_mismatch |= BufferFmt->OriginalType != buffer->OriginalType;
+ }
+ if(fmt_mismatch)
{
context->setError(AL_INVALID_OPERATION, "Queueing buffer with mismatched format");