aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2014-03-04 04:29:35 -0800
committerChris Robinson <[email protected]>2014-03-04 04:29:35 -0800
commitb0a6b6427cfedc194fceee19ddbb7653fca813df (patch)
tree6efa1ab67f121249902d0d7924f861790495828a
parenta6eb38ea7f89ae21d6621570a148aa3aed5edf54 (diff)
Parameterize the block alignment
-rw-r--r--OpenAL32/alBuffer.c263
1 files changed, 152 insertions, 111 deletions
diff --git a/OpenAL32/alBuffer.c b/OpenAL32/alBuffer.c
index bbc1da05..23eb96a1 100644
--- a/OpenAL32/alBuffer.c
+++ b/OpenAL32/alBuffer.c
@@ -43,12 +43,13 @@ extern inline struct ALbuffer *RemoveBuffer(ALCdevice *device, ALuint id);
extern inline ALuint FrameSizeFromUserFmt(enum UserFmtChannels chans, enum UserFmtType type);
extern inline ALuint FrameSizeFromFmt(enum FmtChannels chans, enum FmtType type);
-static ALenum LoadData(ALbuffer *ALBuf, ALuint freq, ALenum NewFormat, ALsizei frames, enum UserFmtChannels chans, enum UserFmtType type, const ALvoid *data, ALboolean storesrc);
-static void ConvertData(ALvoid *dst, enum UserFmtType dstType, const ALvoid *src, enum UserFmtType srcType, ALsizei numchans, ALsizei len);
+static ALenum LoadData(ALbuffer *ALBuf, ALuint freq, ALenum NewFormat, ALsizei frames, enum UserFmtChannels chans, enum UserFmtType type, const ALvoid *data, ALsizei align, ALboolean storesrc);
+static void ConvertData(ALvoid *dst, enum UserFmtType dstType, const ALvoid *src, enum UserFmtType srcType, ALsizei numchans, ALsizei len, ALsizei align);
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);
/*
@@ -303,6 +304,7 @@ AL_API ALvoid AL_APIENTRY alBufferData(ALuint buffer, ALenum format, const ALvoi
ALuint framesize;
ALenum newformat;
ALbuffer *albuf;
+ ALsizei align;
ALenum err;
context = GetContextRef();
@@ -315,6 +317,8 @@ 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)
+ SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
switch(srctype)
{
case UserFmtByte:
@@ -322,12 +326,12 @@ AL_API ALvoid AL_APIENTRY alBufferData(ALuint buffer, ALenum format, const ALvoi
case UserFmtShort:
case UserFmtUShort:
case UserFmtFloat:
- framesize = FrameSizeFromUserFmt(srcchannels, srctype);
- if(!((size%framesize) == 0))
+ framesize = FrameSizeFromUserFmt(srcchannels, srctype) * align;
+ if((size%framesize) != 0)
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
- err = LoadData(albuf, freq, format, size/framesize,
- srcchannels, srctype, data, AL_TRUE);
+ err = LoadData(albuf, freq, format, size/framesize*align,
+ srcchannels, srctype, data, align, AL_TRUE);
if(err != AL_NO_ERROR)
SET_ERROR_AND_GOTO(context, err, done);
break;
@@ -337,8 +341,8 @@ AL_API ALvoid AL_APIENTRY alBufferData(ALuint buffer, ALenum format, const ALvoi
case UserFmtByte3:
case UserFmtUByte3:
case UserFmtDouble:
- framesize = FrameSizeFromUserFmt(srcchannels, srctype);
- if(!((size%framesize) == 0))
+ framesize = FrameSizeFromUserFmt(srcchannels, srctype) * align;
+ if((size%framesize) != 0)
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
newformat = AL_FORMAT_MONO_FLOAT32;
@@ -352,16 +356,16 @@ AL_API ALvoid AL_APIENTRY alBufferData(ALuint buffer, ALenum format, const ALvoi
case UserFmtX61: newformat = AL_FORMAT_61CHN32; break;
case UserFmtX71: newformat = AL_FORMAT_71CHN32; break;
}
- err = LoadData(albuf, freq, newformat, size/framesize,
- srcchannels, srctype, data, AL_TRUE);
+ err = LoadData(albuf, freq, newformat, size/framesize*align,
+ srcchannels, srctype, data, align, AL_TRUE);
if(err != AL_NO_ERROR)
SET_ERROR_AND_GOTO(context, err, done);
break;
case UserFmtMulaw:
case UserFmtAlaw:
- framesize = FrameSizeFromUserFmt(srcchannels, srctype);
- if(!((size%framesize) == 0))
+ framesize = FrameSizeFromUserFmt(srcchannels, srctype) * align;
+ if((size%framesize) != 0)
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
newformat = AL_FORMAT_MONO16;
@@ -375,19 +379,16 @@ AL_API ALvoid AL_APIENTRY alBufferData(ALuint buffer, ALenum format, const ALvoi
case UserFmtX61: newformat = AL_FORMAT_61CHN16; break;
case UserFmtX71: newformat = AL_FORMAT_71CHN16; break;
}
- err = LoadData(albuf, freq, newformat, size/framesize,
- srcchannels, srctype, data, AL_TRUE);
+ err = LoadData(albuf, freq, newformat, size/framesize*align,
+ srcchannels, srctype, data, align, AL_TRUE);
if(err != AL_NO_ERROR)
SET_ERROR_AND_GOTO(context, err, done);
break;
case 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
- */
- framesize = ChannelsFromUserFmt(srcchannels) * 36;
- if(!((size%framesize) == 0))
+ framesize = (align-1)/2 + 4;
+ framesize *= ChannelsFromUserFmt(srcchannels);
+ if((size%framesize) != 0)
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
newformat = AL_FORMAT_MONO16;
@@ -401,8 +402,8 @@ AL_API ALvoid AL_APIENTRY alBufferData(ALuint buffer, ALenum format, const ALvoi
case UserFmtX61: newformat = AL_FORMAT_61CHN16; break;
case UserFmtX71: newformat = AL_FORMAT_71CHN16; break;
}
- err = LoadData(albuf, freq, newformat, size/framesize*65,
- srcchannels, srctype, data, AL_TRUE);
+ err = LoadData(albuf, freq, newformat, size/framesize*align,
+ srcchannels, srctype, data, align, AL_TRUE);
if(err != AL_NO_ERROR)
SET_ERROR_AND_GOTO(context, err, done);
break;
@@ -419,9 +420,10 @@ AL_API ALvoid AL_APIENTRY alBufferSubDataSOFT(ALuint buffer, ALenum format, cons
ALCdevice *device;
ALCcontext *context;
ALbuffer *albuf;
- ALuint original_align;
+ ALuint byte_align;
ALuint channels;
ALuint bytes;
+ ALsizei align;
context = GetContextRef();
if(!context) return;
@@ -435,25 +437,36 @@ AL_API ALvoid AL_APIENTRY alBufferSubDataSOFT(ALuint buffer, ALenum format, cons
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
WriteLock(&albuf->lock);
- if(albuf->OriginalType == UserFmtIMA4)
+ if(GetAlignment(srctype, &align) == AL_FALSE)
{
- ALsizei align = (albuf->OriginalAlign-1)/2 + 4;
- original_align = ChannelsFromUserFmt(albuf->OriginalChannels) * align;
+ WriteUnlock(&albuf->lock);
+ SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
}
- else
+ if(srcchannels != albuf->OriginalChannels || srctype != albuf->OriginalType)
{
- original_align = FrameSizeFromUserFmt(albuf->OriginalChannels,
- albuf->OriginalType) *
- albuf->OriginalAlign;
+ WriteUnlock(&albuf->lock);
+ SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
}
-
- if(srcchannels != albuf->OriginalChannels || srctype != albuf->OriginalType)
+ if(align != albuf->OriginalAlign)
{
WriteUnlock(&albuf->lock);
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
}
+
+ if(albuf->OriginalType == UserFmtIMA4)
+ {
+ byte_align = (albuf->OriginalAlign-1)/2 + 4;
+ byte_align *= ChannelsFromUserFmt(albuf->OriginalChannels);
+ }
+ else
+ {
+ byte_align = albuf->OriginalAlign;
+ byte_align *= FrameSizeFromUserFmt(albuf->OriginalChannels,
+ albuf->OriginalType);
+ }
+
if(offset > albuf->OriginalSize || length > albuf->OriginalSize-offset ||
- (offset%original_align) != 0 || (length%original_align) != 0)
+ (offset%byte_align) != 0 || (length%byte_align) != 0)
{
WriteUnlock(&albuf->lock);
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
@@ -462,19 +475,11 @@ AL_API ALvoid AL_APIENTRY alBufferSubDataSOFT(ALuint buffer, ALenum format, cons
channels = ChannelsFromFmt(albuf->FmtChannels);
bytes = BytesFromFmt(albuf->FmtType);
/* offset -> byte offset, length -> sample count */
- if(srctype == UserFmtIMA4)
- {
- offset = offset/original_align * channels*bytes;
- length = length/original_align * albuf->OriginalAlign;
- }
- else
- {
- ALuint OldBytes = BytesFromUserFmt(srctype);
- offset = offset/OldBytes * bytes;
- length = length/OldBytes/channels;
- }
+ offset = offset/byte_align * channels*bytes;
+ length = length/byte_align * albuf->OriginalAlign;
+
ConvertData((char*)albuf->data+offset, (enum UserFmtType)albuf->FmtType,
- data, srctype, channels, length);
+ data, srctype, channels, length, align);
WriteUnlock(&albuf->lock);
done:
@@ -489,6 +494,7 @@ AL_API void AL_APIENTRY alBufferSamplesSOFT(ALuint buffer,
ALCdevice *device;
ALCcontext *context;
ALbuffer *albuf;
+ ALsizei align;
ALenum err;
context = GetContextRef();
@@ -502,8 +508,13 @@ 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)
+ SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+ if((samples%align) != 0)
+ SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+
err = LoadData(albuf, samplerate, internalformat, samples,
- channels, type, data, AL_FALSE);
+ channels, type, data, align, AL_FALSE);
if(err != AL_NO_ERROR)
SET_ERROR_AND_GOTO(context, err, done);
@@ -517,8 +528,8 @@ AL_API void AL_APIENTRY alBufferSubSamplesSOFT(ALuint buffer,
{
ALCdevice *device;
ALCcontext *context;
- ALuint framesize;
ALbuffer *albuf;
+ ALsizei align;
context = GetContextRef();
if(!context) return;
@@ -532,22 +543,31 @@ AL_API void AL_APIENTRY alBufferSubSamplesSOFT(ALuint buffer,
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
WriteLock(&albuf->lock);
- framesize = FrameSizeFromFmt(albuf->FmtChannels, albuf->FmtType);
+ if(GetAlignment(type, &align) == AL_FALSE)
+ {
+ WriteUnlock(&albuf->lock);
+ SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+ }
if(channels != (ALenum)albuf->FmtChannels)
{
WriteUnlock(&albuf->lock);
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
}
- else if(offset > albuf->SampleLen || samples > albuf->SampleLen-offset)
+ if(offset > albuf->SampleLen || samples > albuf->SampleLen-offset)
+ {
+ WriteUnlock(&albuf->lock);
+ SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+ }
+ if((samples%align) != 0)
{
WriteUnlock(&albuf->lock);
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
}
/* offset -> byte offset */
- offset *= framesize;
+ offset *= FrameSizeFromFmt(albuf->FmtChannels, albuf->FmtType);
ConvertData((char*)albuf->data+offset, (enum UserFmtType)albuf->FmtType,
- data, type, ChannelsFromFmt(albuf->FmtChannels), samples);
+ data, type, ChannelsFromFmt(albuf->FmtChannels), samples, align);
WriteUnlock(&albuf->lock);
done:
@@ -560,8 +580,8 @@ AL_API void AL_APIENTRY alGetBufferSamplesSOFT(ALuint buffer,
{
ALCdevice *device;
ALCcontext *context;
- ALuint framesize;
ALbuffer *albuf;
+ ALsizei align;
context = GetContextRef();
if(!context) return;
@@ -575,7 +595,11 @@ AL_API void AL_APIENTRY alGetBufferSamplesSOFT(ALuint buffer,
SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
ReadLock(&albuf->lock);
- framesize = FrameSizeFromFmt(albuf->FmtChannels, albuf->FmtType);
+ if(GetAlignment(type, &align) == AL_FALSE)
+ {
+ ReadUnlock(&albuf->lock);
+ SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+ }
if(channels != (ALenum)albuf->FmtChannels)
{
ReadUnlock(&albuf->lock);
@@ -586,16 +610,16 @@ AL_API void AL_APIENTRY alGetBufferSamplesSOFT(ALuint buffer,
ReadUnlock(&albuf->lock);
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
}
- if(type == UserFmtIMA4 && (samples%65) != 0)
+ if((samples%align) != 0)
{
ReadUnlock(&albuf->lock);
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
}
/* offset -> byte offset */
- offset *= framesize;
+ offset *= FrameSizeFromFmt(albuf->FmtChannels, albuf->FmtType);
ConvertData(data, type, (char*)albuf->data+offset, (enum UserFmtType)albuf->FmtType,
- ChannelsFromFmt(albuf->FmtChannels), samples);
+ ChannelsFromFmt(albuf->FmtChannels), samples, align);
ReadUnlock(&albuf->lock);
done:
@@ -1068,7 +1092,7 @@ static ALalaw EncodeALaw(ALshort val)
return ((exp<<4) | mant) ^ (sign^0x55);
}
-static void DecodeIMA4Block(ALshort *dst, const ALima4 *src, ALint numchans)
+static void DecodeIMA4Block(ALshort *dst, const ALima4 *src, ALint numchans, ALsizei align)
{
ALint sample[MAX_INPUT_CHANNELS], index[MAX_INPUT_CHANNELS];
ALuint code[MAX_INPUT_CHANNELS];
@@ -1088,8 +1112,7 @@ static void DecodeIMA4Block(ALshort *dst, const ALima4 *src, ALint numchans)
dst[c] = sample[c];
}
- j = 1;
- while(j < 65)
+ for(j = 1;j < align;j += 8)
{
for(c = 0;c < numchans;c++)
{
@@ -1099,7 +1122,7 @@ static void DecodeIMA4Block(ALshort *dst, const ALima4 *src, ALint numchans)
code[c] |= *(src++) << 24;
}
- for(k = 0;k < 8;k++,j++)
+ for(k = 0;k < 8;k++)
{
for(c = 0;c < numchans;c++)
{
@@ -1112,13 +1135,13 @@ static void DecodeIMA4Block(ALshort *dst, const ALima4 *src, ALint numchans)
index[c] += IMA4Index_adjust[nibble];
index[c] = clampi(index[c], 0, 88);
- dst[j*numchans + c] = sample[c];
+ dst[(j+k)*numchans + c] = sample[c];
}
}
}
}
-static void EncodeIMA4Block(ALima4 *dst, const ALshort *src, ALint *sample, ALint *index, ALint numchans)
+static void EncodeIMA4Block(ALima4 *dst, const ALshort *src, ALint *sample, ALint *index, ALint numchans, ALsizei align)
{
ALsizei j,k,c;
@@ -1150,8 +1173,7 @@ static void EncodeIMA4Block(ALima4 *dst, const ALshort *src, ALint *sample, ALin
*(dst++) = (index[c]>>8) & 0xff;
}
- j = 1;
- while(j < 65)
+ for(j = 1;j < align;j += 8)
{
for(c = 0;c < numchans;c++)
{
@@ -1181,7 +1203,6 @@ static void EncodeIMA4Block(ALima4 *dst, const ALshort *src, ALint *sample, ALin
else *(dst++) |= nibble<<4;
}
}
- j += 8;
}
}
@@ -1560,7 +1581,7 @@ static inline ALubyte3 Conv_ALubyte3_ALubyte3(ALubyte3 val)
#define DECL_TEMPLATE(T1, T2) \
static void Convert_##T1##_##T2(T1 *dst, const T2 *src, ALuint numchans, \
- ALuint len) \
+ ALuint len, ALsizei UNUSED(align)) \
{ \
ALuint i, j; \
for(i = 0;i < len;i++) \
@@ -1602,18 +1623,19 @@ DECL_TEMPLATE2(ALubyte3)
#define DECL_TEMPLATE(T) \
static void Convert_##T##_ALima4(T *dst, const ALima4 *src, ALuint numchans, \
- ALuint len) \
+ ALuint len, ALuint align) \
{ \
+ ALsizei byte_align = (align-1)/2 + 4; \
ALuint i, j, k; \
ALshort *tmp; \
\
- tmp = alloca(65*numchans); \
- for(i = 0;i < len;) \
+ tmp = alloca(align*numchans); \
+ for(i = 0;i < len;i += align) \
{ \
- DecodeIMA4Block(tmp, src, numchans); \
- src += 36*numchans; \
+ DecodeIMA4Block(tmp, src, numchans, align); \
+ src += byte_align*numchans; \
\
- for(j = 0;j < 65 && i < len;j++,i++) \
+ for(j = 0;j < align;j++) \
{ \
for(k = 0;k < numchans;k++) \
*(dst++) = Conv_##T##_ALshort(tmp[j*numchans + k]); \
@@ -1638,20 +1660,21 @@ DECL_TEMPLATE(ALubyte3)
#define DECL_TEMPLATE(T) \
static void Convert_ALima4_##T(ALima4 *dst, const T *src, ALuint numchans, \
- ALuint len) \
+ ALuint len, ALuint align) \
{ \
ALint sample[MaxChannels] = {0,0,0,0,0,0,0,0}; \
ALint index[MaxChannels] = {0,0,0,0,0,0,0,0}; \
+ ALsizei byte_align = (align-1)/2 + 4; \
ALshort *tmp; \
ALuint i, j; \
\
- tmp = alloca(65*numchans); \
- for(i = 0;i < len;i += 65) \
+ tmp = alloca(align*numchans); \
+ for(i = 0;i < len;i += align) \
{ \
- for(j = 0;j < 65*numchans;j++) \
+ for(j = 0;j < align*numchans;j++) \
tmp[j] = Conv_ALshort_##T(*(src++)); \
- EncodeIMA4Block(dst, tmp, sample, index, numchans); \
- dst += 36*numchans; \
+ EncodeIMA4Block(dst, tmp, sample, index, numchans, align); \
+ dst += byte_align*numchans; \
} \
}
@@ -1666,7 +1689,8 @@ DECL_TEMPLATE(ALdouble)
DECL_TEMPLATE(ALmulaw)
DECL_TEMPLATE(ALalaw)
static void Convert_ALima4_ALima4(ALima4* UNUSED(dst), const ALima4* UNUSED(src),
- ALuint UNUSED(numchans), ALuint UNUSED(len))
+ ALuint UNUSED(numchans), ALuint UNUSED(len),
+ ALuint UNUSED(align))
{
/* We don't store IMA4 samples internally, so IMA4-to-IMA4 conversions
* should never happen. */
@@ -1679,48 +1703,48 @@ DECL_TEMPLATE(ALubyte3)
#define DECL_TEMPLATE(T) \
static void Convert_##T(T *dst, const ALvoid *src, enum UserFmtType srcType, \
- ALsizei numchans, ALsizei len) \
+ ALsizei numchans, ALsizei len, ALsizei align) \
{ \
switch(srcType) \
{ \
case UserFmtByte: \
- Convert_##T##_ALbyte(dst, src, numchans, len); \
+ Convert_##T##_ALbyte(dst, src, numchans, len, align); \
break; \
case UserFmtUByte: \
- Convert_##T##_ALubyte(dst, src, numchans, len); \
+ Convert_##T##_ALubyte(dst, src, numchans, len, align); \
break; \
case UserFmtShort: \
- Convert_##T##_ALshort(dst, src, numchans, len); \
+ Convert_##T##_ALshort(dst, src, numchans, len, align); \
break; \
case UserFmtUShort: \
- Convert_##T##_ALushort(dst, src, numchans, len); \
+ Convert_##T##_ALushort(dst, src, numchans, len, align); \
break; \
case UserFmtInt: \
- Convert_##T##_ALint(dst, src, numchans, len); \
+ Convert_##T##_ALint(dst, src, numchans, len, align); \
break; \
case UserFmtUInt: \
- Convert_##T##_ALuint(dst, src, numchans, len); \
+ Convert_##T##_ALuint(dst, src, numchans, len, align); \
break; \
case UserFmtFloat: \
- Convert_##T##_ALfloat(dst, src, numchans, len); \
+ Convert_##T##_ALfloat(dst, src, numchans, len, align); \
break; \
case UserFmtDouble: \
- Convert_##T##_ALdouble(dst, src, numchans, len); \
+ Convert_##T##_ALdouble(dst, src, numchans, len, align); \
break; \
case UserFmtMulaw: \
- Convert_##T##_ALmulaw(dst, src, numchans, len); \
+ Convert_##T##_ALmulaw(dst, src, numchans, len, align); \
break; \
case UserFmtAlaw: \
- Convert_##T##_ALalaw(dst, src, numchans, len); \
+ Convert_##T##_ALalaw(dst, src, numchans, len, align); \
break; \
case UserFmtIMA4: \
- Convert_##T##_ALima4(dst, src, numchans, len); \
+ Convert_##T##_ALima4(dst, src, numchans, len, align); \
break; \
case UserFmtByte3: \
- Convert_##T##_ALbyte3(dst, src, numchans, len); \
+ Convert_##T##_ALbyte3(dst, src, numchans, len, align); \
break; \
case UserFmtUByte3: \
- Convert_##T##_ALubyte3(dst, src, numchans, len); \
+ Convert_##T##_ALubyte3(dst, src, numchans, len, align); \
break; \
} \
}
@@ -1742,48 +1766,48 @@ DECL_TEMPLATE(ALubyte3)
#undef DECL_TEMPLATE
-static void ConvertData(ALvoid *dst, enum UserFmtType dstType, const ALvoid *src, enum UserFmtType srcType, ALsizei numchans, ALsizei len)
+static void ConvertData(ALvoid *dst, enum UserFmtType dstType, const ALvoid *src, enum UserFmtType srcType, ALsizei numchans, ALsizei len, ALsizei align)
{
switch(dstType)
{
case UserFmtByte:
- Convert_ALbyte(dst, src, srcType, numchans, len);
+ Convert_ALbyte(dst, src, srcType, numchans, len, align);
break;
case UserFmtUByte:
- Convert_ALubyte(dst, src, srcType, numchans, len);
+ Convert_ALubyte(dst, src, srcType, numchans, len, align);
break;
case UserFmtShort:
- Convert_ALshort(dst, src, srcType, numchans, len);
+ Convert_ALshort(dst, src, srcType, numchans, len, align);
break;
case UserFmtUShort:
- Convert_ALushort(dst, src, srcType, numchans, len);
+ Convert_ALushort(dst, src, srcType, numchans, len, align);
break;
case UserFmtInt:
- Convert_ALint(dst, src, srcType, numchans, len);
+ Convert_ALint(dst, src, srcType, numchans, len, align);
break;
case UserFmtUInt:
- Convert_ALuint(dst, src, srcType, numchans, len);
+ Convert_ALuint(dst, src, srcType, numchans, len, align);
break;
case UserFmtFloat:
- Convert_ALfloat(dst, src, srcType, numchans, len);
+ Convert_ALfloat(dst, src, srcType, numchans, len, align);
break;
case UserFmtDouble:
- Convert_ALdouble(dst, src, srcType, numchans, len);
+ Convert_ALdouble(dst, src, srcType, numchans, len, align);
break;
case UserFmtMulaw:
- Convert_ALmulaw(dst, src, srcType, numchans, len);
+ Convert_ALmulaw(dst, src, srcType, numchans, len, align);
break;
case UserFmtAlaw:
- Convert_ALalaw(dst, src, srcType, numchans, len);
+ Convert_ALalaw(dst, src, srcType, numchans, len, align);
break;
case UserFmtIMA4:
- Convert_ALima4(dst, src, srcType, numchans, len);
+ Convert_ALima4(dst, src, srcType, numchans, len, align);
break;
case UserFmtByte3:
- Convert_ALbyte3(dst, src, srcType, numchans, len);
+ Convert_ALbyte3(dst, src, srcType, numchans, len, align);
break;
case UserFmtUByte3:
- Convert_ALubyte3(dst, src, srcType, numchans, len);
+ Convert_ALubyte3(dst, src, srcType, numchans, len, align);
break;
}
}
@@ -1796,7 +1820,7 @@ static void ConvertData(ALvoid *dst, enum UserFmtType dstType, const ALvoid *src
* Currently, the new format must have the same channel configuration as the
* original format.
*/
-static ALenum LoadData(ALbuffer *ALBuf, ALuint freq, ALenum NewFormat, ALsizei frames, enum UserFmtChannels SrcChannels, enum UserFmtType SrcType, const ALvoid *data, ALboolean storesrc)
+static ALenum LoadData(ALbuffer *ALBuf, ALuint freq, ALenum NewFormat, ALsizei frames, enum UserFmtChannels SrcChannels, enum UserFmtType SrcType, const ALvoid *data, ALsizei align, ALboolean storesrc)
{
ALuint NewChannels, NewBytes;
enum FmtChannels DstChannels;
@@ -1833,7 +1857,7 @@ static ALenum LoadData(ALbuffer *ALBuf, ALuint freq, ALenum NewFormat, ALsizei f
ALBuf->data = temp;
if(data != NULL)
- ConvertData(ALBuf->data, (enum UserFmtType)DstType, data, SrcType, NewChannels, frames);
+ ConvertData(ALBuf->data, (enum UserFmtType)DstType, data, SrcType, NewChannels, frames, align);
if(storesrc)
{
@@ -1841,8 +1865,9 @@ static ALenum LoadData(ALbuffer *ALBuf, ALuint freq, ALenum NewFormat, ALsizei f
ALBuf->OriginalType = SrcType;
if(SrcType == UserFmtIMA4)
{
- ALBuf->OriginalSize = frames / 65 * 36 * ChannelsFromUserFmt(SrcChannels);
- ALBuf->OriginalAlign = 65;
+ ALsizei byte_align = ((align-1)/2 + 4) * ChannelsFromUserFmt(SrcChannels);
+ ALBuf->OriginalSize = frames / align * byte_align;
+ ALBuf->OriginalAlign = align;
}
else
{
@@ -2050,6 +2075,22 @@ static ALboolean DecomposeFormat(ALenum format, enum FmtChannels *chans, enum Fm
return AL_FALSE;
}
+static ALboolean GetAlignment(enum UserFmtType type, ALsizei *align)
+{
+ 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;
+}
+
static ALboolean IsValidType(ALenum type)
{