diff options
author | Chris Robinson <[email protected]> | 2014-03-04 05:16:45 -0800 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2014-03-04 05:53:35 -0800 |
commit | f3a87d72b266640a706ddd3234aa4313b53cabce (patch) | |
tree | af906bac99467fc9407f4d94fbddc678ab3f80a1 /OpenAL32 | |
parent | b0a6b6427cfedc194fceee19ddbb7653fca813df (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.h | 3 | ||||
-rw-r--r-- | OpenAL32/Include/alMain.h | 6 | ||||
-rw-r--r-- | OpenAL32/alBuffer.c | 87 |
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; } |