aboutsummaryrefslogtreecommitdiffstats
path: root/OpenAL32
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2014-03-04 05:16:45 -0800
committerChris Robinson <[email protected]>2014-03-04 05:53:35 -0800
commitf3a87d72b266640a706ddd3234aa4313b53cabce (patch)
treeaf906bac99467fc9407f4d94fbddc678ab3f80a1 /OpenAL32
parentb0a6b6427cfedc194fceee19ddbb7653fca813df (diff)
Add an extension to alter the block alignment for buffer unpack/pack ops
This is for unpacking (reading, e.g. alBufferData) and packing (writing, e.g. alGetBufferSamplesSOFT) operations. The alignments are specified in sample frames, with 0 meaning the default (65 for IMA4, 1 otherwise). IMA4 alignment must be a multiple of 8, plus 1 (e.g. alignment = n*8 + 1), otherwise an error will occur during (un)packing. Chenging the block alignment does not affect already-loaded sample data, only future unpack/pack operations... so for example, this is perfectly valid: // Load mono IMA4 data with a block alignment of 1024 bytes, or 2041 sample // frames. alBufferi(buffer, AL_UNPACK_BLOCK_ALIGNMENT_SOFT, 2041); alBufferData(buffer, AL_FORMAT_MONO_IMA4, data, data_len, srate); alBufferi(buffer, AL_UNPACK_BLOCK_ALIGNMENT_SOFT, 0);
Diffstat (limited to 'OpenAL32')
-rw-r--r--OpenAL32/Include/alBuffer.h3
-rw-r--r--OpenAL32/Include/alMain.h6
-rw-r--r--OpenAL32/alBuffer.c87
3 files changed, 80 insertions, 16 deletions
diff --git a/OpenAL32/Include/alBuffer.h b/OpenAL32/Include/alBuffer.h
index 60f406c8..be426df2 100644
--- a/OpenAL32/Include/alBuffer.h
+++ b/OpenAL32/Include/alBuffer.h
@@ -84,6 +84,9 @@ typedef struct ALbuffer {
ALsizei LoopStart;
ALsizei LoopEnd;
+ ALsizei UnpackAlign;
+ ALsizei PackAlign;
+
/* Number of times buffer was attached to a source (deletion can only occur when 0) */
RefCount ref;
diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h
index 06fb954c..7de52260 100644
--- a/OpenAL32/Include/alMain.h
+++ b/OpenAL32/Include/alMain.h
@@ -240,6 +240,12 @@ ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname,
#endif
#endif
+#ifndef AL_SOFT_block_alignment
+#define AL_SOFT_block_alignment 1
+#define AL_UNPACK_BLOCK_ALIGNMENT_SOFT 0x200C
+#define AL_PACK_BLOCK_ALIGNMENT_SOFT 0x200D
+#endif
+
#ifdef IN_IDE_PARSER
/* KDevelop's parser doesn't recognize the C99-standard restrict keyword, but
diff --git a/OpenAL32/alBuffer.c b/OpenAL32/alBuffer.c
index 23eb96a1..058b1f49 100644
--- a/OpenAL32/alBuffer.c
+++ b/OpenAL32/alBuffer.c
@@ -49,7 +49,7 @@ static ALboolean IsValidType(ALenum type);
static ALboolean IsValidChannels(ALenum channels);
static ALboolean DecomposeUserFormat(ALenum format, enum UserFmtChannels *chans, enum UserFmtType *type);
static ALboolean DecomposeFormat(ALenum format, enum FmtChannels *chans, enum FmtType *type);
-static ALboolean GetAlignment(enum UserFmtType type, ALsizei *align);
+static ALboolean SanitizeAlignment(enum UserFmtType type, ALsizei *align);
/*
@@ -317,7 +317,9 @@ AL_API ALvoid AL_APIENTRY alBufferData(ALuint buffer, ALenum format, const ALvoi
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
if(DecomposeUserFormat(format, &srcchannels, &srctype) == AL_FALSE)
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
- if(GetAlignment(srctype, &align) == AL_FALSE)
+
+ align = albuf->UnpackAlign;
+ if(SanitizeAlignment(srctype, &align) == AL_FALSE)
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
switch(srctype)
{
@@ -437,7 +439,8 @@ AL_API ALvoid AL_APIENTRY alBufferSubDataSOFT(ALuint buffer, ALenum format, cons
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
WriteLock(&albuf->lock);
- if(GetAlignment(srctype, &align) == AL_FALSE)
+ align = albuf->UnpackAlign;
+ if(SanitizeAlignment(srctype, &align) == AL_FALSE)
{
WriteUnlock(&albuf->lock);
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
@@ -508,7 +511,8 @@ AL_API void AL_APIENTRY alBufferSamplesSOFT(ALuint buffer,
if(IsValidType(type) == AL_FALSE || IsValidChannels(channels) == AL_FALSE)
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
- if(GetAlignment(type, &align) == AL_FALSE)
+ align = albuf->UnpackAlign;
+ if(SanitizeAlignment(type, &align) == AL_FALSE)
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
if((samples%align) != 0)
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
@@ -543,7 +547,8 @@ AL_API void AL_APIENTRY alBufferSubSamplesSOFT(ALuint buffer,
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
WriteLock(&albuf->lock);
- if(GetAlignment(type, &align) == AL_FALSE)
+ align = albuf->UnpackAlign;
+ if(SanitizeAlignment(type, &align) == AL_FALSE)
{
WriteUnlock(&albuf->lock);
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
@@ -595,7 +600,8 @@ AL_API void AL_APIENTRY alGetBufferSamplesSOFT(ALuint buffer,
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
ReadLock(&albuf->lock);
- if(GetAlignment(type, &align) == AL_FALSE)
+ align = albuf->PackAlign;
+ if(SanitizeAlignment(type, &align) == AL_FALSE)
{
ReadUnlock(&albuf->lock);
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
@@ -715,20 +721,33 @@ done:
}
-AL_API void AL_APIENTRY alBufferi(ALuint buffer, ALenum param, ALint UNUSED(value))
+AL_API void AL_APIENTRY alBufferi(ALuint buffer, ALenum param, ALint value)
{
ALCdevice *device;
ALCcontext *context;
+ ALbuffer *albuf;
context = GetContextRef();
if(!context) return;
device = context->Device;
- if(LookupBuffer(device, buffer) == NULL)
+ if((albuf=LookupBuffer(device, buffer)) == NULL)
SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
switch(param)
{
+ case AL_UNPACK_BLOCK_ALIGNMENT_SOFT:
+ if(!(value >= 0))
+ SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+ ExchangeInt(&albuf->UnpackAlign, value);
+ break;
+
+ case AL_PACK_BLOCK_ALIGNMENT_SOFT:
+ if(!(value >= 0))
+ SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+ ExchangeInt(&albuf->PackAlign, value);
+ break;
+
default:
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
}
@@ -767,6 +786,17 @@ AL_API void AL_APIENTRY alBufferiv(ALuint buffer, ALenum param, const ALint *val
ALCcontext *context;
ALbuffer *albuf;
+ if(values)
+ {
+ switch(param)
+ {
+ case AL_UNPACK_BLOCK_ALIGNMENT_SOFT:
+ case AL_PACK_BLOCK_ALIGNMENT_SOFT:
+ alBufferi(buffer, param, values[0]);
+ return;
+ }
+ }
+
context = GetContextRef();
if(!context) return;
@@ -946,6 +976,14 @@ AL_API ALvoid AL_APIENTRY alGetBufferi(ALuint buffer, ALenum param, ALint *value
*value = albuf->SampleLen;
break;
+ case AL_UNPACK_BLOCK_ALIGNMENT_SOFT:
+ *value = albuf->UnpackAlign;
+ break;
+
+ case AL_PACK_BLOCK_ALIGNMENT_SOFT:
+ *value = albuf->PackAlign;
+ break;
+
default:
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
}
@@ -995,6 +1033,8 @@ AL_API void AL_APIENTRY alGetBufferiv(ALuint buffer, ALenum param, ALint *values
case AL_INTERNAL_FORMAT_SOFT:
case AL_BYTE_LENGTH_SOFT:
case AL_SAMPLE_LENGTH_SOFT:
+ case AL_UNPACK_BLOCK_ALIGNMENT_SOFT:
+ case AL_PACK_BLOCK_ALIGNMENT_SOFT:
alGetBufferi(buffer, param, values);
return;
}
@@ -2075,18 +2115,33 @@ static ALboolean DecomposeFormat(ALenum format, enum FmtChannels *chans, enum Fm
return AL_FALSE;
}
-static ALboolean GetAlignment(enum UserFmtType type, ALsizei *align)
+static ALboolean SanitizeAlignment(enum UserFmtType type, ALsizei *align)
{
+ if(*align < 0)
+ return AL_FALSE;
+
+ if(*align == 0)
+ {
+ if(type == UserFmtIMA4)
+ {
+ /* Here is where things vary:
+ * nVidia and Apple use 64+1 sample frames per block -> block_size=36 bytes per channel
+ * Most PC sound software uses 2040+1 sample frames per block -> block_size=1024 bytes per channel
+ */
+ *align = 65;
+ }
+ else
+ *align = 1;
+ return AL_TRUE;
+ }
+
if(type == UserFmtIMA4)
{
- /* Here is where things vary:
- * nVidia and Apple use 64+1 sample frames per block -> block_size=36 bytes per channel
- * Most PC sound software uses 2040+1 sample frames per block -> block_size=1024 bytes per channel
- */
- *align = 65;
+ /* IMA4 block alignment must be a multiple of 8, plus 1. */
+ if(((*align)&7) != 1)
+ return AL_FALSE;
+ return AL_TRUE;
}
- else
- *align = 1;
return AL_TRUE;
}