Add an extension to support MSADPCM buffer formats
This commit is contained in:
@@ -445,6 +445,8 @@ static const ALCenums enumeration[] = {
|
||||
DECL(AL_FORMAT_STEREO_DOUBLE_EXT),
|
||||
DECL(AL_FORMAT_MONO_IMA4),
|
||||
DECL(AL_FORMAT_STEREO_IMA4),
|
||||
DECL(AL_FORMAT_MONO_MSADPCM_SOFT),
|
||||
DECL(AL_FORMAT_STEREO_MSADPCM_SOFT),
|
||||
DECL(AL_FORMAT_QUAD8_LOKI),
|
||||
DECL(AL_FORMAT_QUAD16_LOKI),
|
||||
DECL(AL_FORMAT_QUAD8),
|
||||
@@ -710,7 +712,7 @@ static const ALchar alExtList[] =
|
||||
"AL_EXT_MULAW_MCFORMATS AL_EXT_OFFSET AL_EXT_source_distance_model "
|
||||
"AL_LOKI_quadriphonic AL_SOFTX_block_alignment AL_SOFT_buffer_samples "
|
||||
"AL_SOFT_buffer_sub_data AL_SOFT_deferred_updates AL_SOFT_direct_channels "
|
||||
"AL_SOFT_loop_points AL_SOFT_source_latency";
|
||||
"AL_SOFT_loop_points AL_SOFTX_MSADPCM AL_SOFT_source_latency";
|
||||
|
||||
static volatile ALCenum LastNullDeviceError = ALC_NO_ERROR;
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ enum UserFmtType {
|
||||
UserFmtMulaw,
|
||||
UserFmtAlaw,
|
||||
UserFmtIMA4,
|
||||
UserFmtMSADPCM,
|
||||
};
|
||||
enum UserFmtChannels {
|
||||
UserFmtMono = AL_MONO_SOFT,
|
||||
|
||||
@@ -246,6 +246,12 @@ ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname,
|
||||
#define AL_PACK_BLOCK_ALIGNMENT_SOFT 0x200D
|
||||
#endif
|
||||
|
||||
#ifndef AL_SOFT_MSADPCM
|
||||
#define AL_SOFT_MSADPCM 1
|
||||
#define AL_FORMAT_MONO_MSADPCM_SOFT 0x1302
|
||||
#define AL_FORMAT_STEREO_MSADPCM_SOFT 0x1303
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef IN_IDE_PARSER
|
||||
/* KDevelop's parser doesn't recognize the C99-standard restrict keyword, but
|
||||
|
||||
+311
-29
@@ -81,6 +81,25 @@ static const int IMA4Index_adjust[16] = {
|
||||
-1,-1,-1,-1, 2, 4, 6, 8
|
||||
};
|
||||
|
||||
|
||||
/* MSADPCM Adaption table */
|
||||
static const int MSADPCMAdaption[16] = {
|
||||
230, 230, 230, 230, 307, 409, 512, 614,
|
||||
768, 614, 512, 409, 307, 230, 230, 230
|
||||
};
|
||||
|
||||
/* MSADPCM Adaption Coefficient tables */
|
||||
static const int MSADPCMAdaptionCoeff[7][2] = {
|
||||
{ 256, 0 },
|
||||
{ 512, -256 },
|
||||
{ 0, 0 },
|
||||
{ 192, 64 },
|
||||
{ 240, 0 },
|
||||
{ 460, -208 },
|
||||
{ 392, -232 }
|
||||
};
|
||||
|
||||
|
||||
/* A quick'n'dirty lookup table to decode a muLaw-encoded byte sample into a
|
||||
* signed 16-bit sample */
|
||||
static const ALshort muLawDecompressionTable[256] = {
|
||||
@@ -409,6 +428,29 @@ AL_API ALvoid AL_APIENTRY alBufferData(ALuint buffer, ALenum format, const ALvoi
|
||||
if(err != AL_NO_ERROR)
|
||||
SET_ERROR_AND_GOTO(context, err, done);
|
||||
break;
|
||||
|
||||
case UserFmtMSADPCM:
|
||||
framesize = (align-2)/2 + 7;
|
||||
framesize *= ChannelsFromUserFmt(srcchannels);
|
||||
if((size%framesize) != 0)
|
||||
SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
|
||||
|
||||
newformat = AL_FORMAT_MONO16;
|
||||
switch(srcchannels)
|
||||
{
|
||||
case UserFmtMono: newformat = AL_FORMAT_MONO16; break;
|
||||
case UserFmtStereo: newformat = AL_FORMAT_STEREO16; break;
|
||||
case UserFmtRear: newformat = AL_FORMAT_REAR16; break;
|
||||
case UserFmtQuad: newformat = AL_FORMAT_QUAD16; break;
|
||||
case UserFmtX51: newformat = AL_FORMAT_51CHN16; break;
|
||||
case UserFmtX61: newformat = AL_FORMAT_61CHN16; break;
|
||||
case UserFmtX71: newformat = AL_FORMAT_71CHN16; break;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
done:
|
||||
@@ -461,6 +503,11 @@ AL_API ALvoid AL_APIENTRY alBufferSubDataSOFT(ALuint buffer, ALenum format, cons
|
||||
byte_align = (albuf->OriginalAlign-1)/2 + 4;
|
||||
byte_align *= ChannelsFromUserFmt(albuf->OriginalChannels);
|
||||
}
|
||||
else if(albuf->OriginalType == UserFmtMSADPCM)
|
||||
{
|
||||
byte_align = (albuf->OriginalAlign-2)/2 + 7;
|
||||
byte_align *= ChannelsFromUserFmt(albuf->OriginalChannels);
|
||||
}
|
||||
else
|
||||
{
|
||||
byte_align = albuf->OriginalAlign;
|
||||
@@ -1069,6 +1116,7 @@ done:
|
||||
typedef ALubyte ALmulaw;
|
||||
typedef ALubyte ALalaw;
|
||||
typedef ALubyte ALima4;
|
||||
typedef ALubyte ALmsadpcm;
|
||||
typedef struct {
|
||||
ALbyte b[3];
|
||||
} ALbyte3;
|
||||
@@ -1247,6 +1295,118 @@ static void EncodeIMA4Block(ALima4 *dst, const ALshort *src, ALint *sample, ALin
|
||||
}
|
||||
|
||||
|
||||
static void DecodeMSADPCMBlock(ALshort *dst, const ALmsadpcm *src, ALint numchans, ALsizei align)
|
||||
{
|
||||
ALubyte blockpred[MAX_INPUT_CHANNELS];
|
||||
ALint delta[MAX_INPUT_CHANNELS];
|
||||
ALshort samples[MAX_INPUT_CHANNELS][2];
|
||||
ALint i, j;
|
||||
|
||||
for(i = 0;i < numchans;i++)
|
||||
{
|
||||
blockpred[i] = *(src++);
|
||||
blockpred[i] = minu(blockpred[i], 6);
|
||||
}
|
||||
for(i = 0;i < numchans;i++)
|
||||
{
|
||||
delta[i] = *(src++);
|
||||
delta[i] |= *(src++) << 8;
|
||||
}
|
||||
for(i = 0;i < numchans;i++)
|
||||
{
|
||||
samples[i][0] = *(src++);
|
||||
samples[i][0] |= *(src++) << 8;
|
||||
samples[i][0] = (samples[i][0]^0x8000) - 0x8000;
|
||||
}
|
||||
for(i = 0;i < numchans;i++)
|
||||
{
|
||||
samples[i][1] = *(src++);
|
||||
samples[i][1] |= *(src++) << 8;
|
||||
samples[i][1] = (samples[i][1]^0x8000) - 0x8000;
|
||||
}
|
||||
|
||||
/* Second sample is written first. */
|
||||
for(i = 0;i < numchans;i++)
|
||||
*(dst++) = samples[i][1];
|
||||
for(i = 0;i < numchans;i++)
|
||||
*(dst++) = samples[i][0];
|
||||
|
||||
for(j = 2;j < align;j++)
|
||||
{
|
||||
for(i = 0;i < numchans;i++)
|
||||
{
|
||||
const ALint num = (j*numchans) + i;
|
||||
ALint nibble, pred;
|
||||
|
||||
/* Read the nibble and sign-expand it. */
|
||||
if(!(num&1))
|
||||
nibble = (*src>>4)&0x0f;
|
||||
else
|
||||
nibble = (*(src++))&0x0f;
|
||||
nibble = (nibble^0x08) - 0x08;
|
||||
|
||||
pred = (samples[i][0]*MSADPCMAdaptionCoeff[blockpred[i]][0] +
|
||||
samples[i][1]*MSADPCMAdaptionCoeff[blockpred[i]][1]) / 256;
|
||||
pred += nibble * delta[i];
|
||||
pred = clampi(pred, -32768, 32767);
|
||||
|
||||
samples[i][1] = samples[i][0];
|
||||
samples[i][0] = pred;
|
||||
|
||||
delta[i] = (MSADPCMAdaption[nibble&0x0f] * delta[i]) / 256;
|
||||
delta[i] = maxu(16, delta[i]);
|
||||
|
||||
*(dst++) = pred;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* FIXME: Stubbed. Just inserts silence. */
|
||||
static void EncodeMSADPCMBlock(ALmsadpcm *dst, const ALshort* UNUSED(src), ALint* UNUSED(sample), ALint* UNUSED(index), ALint numchans, ALsizei align)
|
||||
{
|
||||
ALint i, j;
|
||||
|
||||
/* Block predictor */
|
||||
for(i = 0;i < numchans;i++)
|
||||
*(dst++) = 2;
|
||||
/* Initial delta */
|
||||
for(i = 0;i < numchans;i++)
|
||||
{
|
||||
*(dst++) = 16;
|
||||
*(dst++) = 0;
|
||||
}
|
||||
/* Initial sample 1 */
|
||||
for(i = 0;i < numchans;i++)
|
||||
{
|
||||
*(dst++) = 0;
|
||||
*(dst++) = 0;
|
||||
}
|
||||
/* Initial sample 2 */
|
||||
for(i = 0;i < numchans;i++)
|
||||
{
|
||||
*(dst++) = 0;
|
||||
*(dst++) = 0;
|
||||
}
|
||||
|
||||
for(j = 2;j < align;j++)
|
||||
{
|
||||
for(i = 0;i < numchans;i++)
|
||||
{
|
||||
const ALint num = (j*numchans) + i;
|
||||
ALubyte nibble = 0;
|
||||
|
||||
if(!(num&1))
|
||||
*dst = nibble << 4;
|
||||
else
|
||||
{
|
||||
*dst |= nibble;
|
||||
dst++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static inline ALint DecodeByte3(ALbyte3 val)
|
||||
{
|
||||
if(IS_LITTLE_ENDIAN)
|
||||
@@ -1665,7 +1825,7 @@ DECL_TEMPLATE2(ALubyte3)
|
||||
static void Convert_##T##_ALima4(T *dst, const ALima4 *src, ALuint numchans, \
|
||||
ALuint len, ALuint align) \
|
||||
{ \
|
||||
ALsizei byte_align = (align-1)/2 + 4; \
|
||||
ALsizei byte_align = ((align-1)/2 + 4) * numchans; \
|
||||
ALuint i, j, k; \
|
||||
ALshort *tmp; \
|
||||
\
|
||||
@@ -1673,7 +1833,7 @@ static void Convert_##T##_ALima4(T *dst, const ALima4 *src, ALuint numchans, \
|
||||
for(i = 0;i < len;i += align) \
|
||||
{ \
|
||||
DecodeIMA4Block(tmp, src, numchans, align); \
|
||||
src += byte_align*numchans; \
|
||||
src += byte_align; \
|
||||
\
|
||||
for(j = 0;j < align;j++) \
|
||||
{ \
|
||||
@@ -1704,7 +1864,7 @@ static void Convert_ALima4_##T(ALima4 *dst, const T *src, ALuint numchans, \
|
||||
{ \
|
||||
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; \
|
||||
ALsizei byte_align = ((align-1)/2 + 4) * numchans; \
|
||||
ALshort *tmp; \
|
||||
ALuint i, j; \
|
||||
\
|
||||
@@ -1714,7 +1874,7 @@ static void Convert_ALima4_##T(ALima4 *dst, const T *src, ALuint numchans, \
|
||||
for(j = 0;j < align*numchans;j++) \
|
||||
tmp[j] = Conv_ALshort_##T(*(src++)); \
|
||||
EncodeIMA4Block(dst, tmp, sample, index, numchans, align); \
|
||||
dst += byte_align*numchans; \
|
||||
dst += byte_align; \
|
||||
} \
|
||||
}
|
||||
|
||||
@@ -1728,19 +1888,118 @@ DECL_TEMPLATE(ALfloat)
|
||||
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(align))
|
||||
{
|
||||
/* We don't store IMA4 samples internally, so IMA4-to-IMA4 conversions
|
||||
* should never happen. */
|
||||
ERR("Unexpected IMA4-to-IMA4 conversion!\n");
|
||||
}
|
||||
DECL_TEMPLATE(ALbyte3)
|
||||
DECL_TEMPLATE(ALubyte3)
|
||||
|
||||
#undef DECL_TEMPLATE
|
||||
|
||||
|
||||
#define DECL_TEMPLATE(T) \
|
||||
static void Convert_##T##_ALmsadpcm(T *dst, const ALmsadpcm *src, \
|
||||
ALuint numchans, ALuint len, \
|
||||
ALuint align) \
|
||||
{ \
|
||||
ALsizei byte_align = ((align-2)/2 + 7) * numchans; \
|
||||
ALuint i, j, k; \
|
||||
ALshort *tmp; \
|
||||
\
|
||||
tmp = alloca(align*numchans); \
|
||||
for(i = 0;i < len;i += align) \
|
||||
{ \
|
||||
DecodeMSADPCMBlock(tmp, src, numchans, align); \
|
||||
src += byte_align; \
|
||||
\
|
||||
for(j = 0;j < align;j++) \
|
||||
{ \
|
||||
for(k = 0;k < numchans;k++) \
|
||||
*(dst++) = Conv_##T##_ALshort(tmp[j*numchans + k]); \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
DECL_TEMPLATE(ALbyte)
|
||||
DECL_TEMPLATE(ALubyte)
|
||||
DECL_TEMPLATE(ALshort)
|
||||
DECL_TEMPLATE(ALushort)
|
||||
DECL_TEMPLATE(ALint)
|
||||
DECL_TEMPLATE(ALuint)
|
||||
DECL_TEMPLATE(ALfloat)
|
||||
DECL_TEMPLATE(ALdouble)
|
||||
DECL_TEMPLATE(ALmulaw)
|
||||
DECL_TEMPLATE(ALalaw)
|
||||
DECL_TEMPLATE(ALbyte3)
|
||||
DECL_TEMPLATE(ALubyte3)
|
||||
|
||||
#undef DECL_TEMPLATE
|
||||
|
||||
#define DECL_TEMPLATE(T) \
|
||||
static void Convert_ALmsadpcm_##T(ALmsadpcm *dst, const T *src, \
|
||||
ALuint numchans, 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-2)/2 + 7) * numchans; \
|
||||
ALshort *tmp; \
|
||||
ALuint i, j; \
|
||||
\
|
||||
ERR("MSADPCM encoding not currently supported!\n"); \
|
||||
\
|
||||
tmp = alloca(align*numchans); \
|
||||
for(i = 0;i < len;i += align) \
|
||||
{ \
|
||||
for(j = 0;j < align*numchans;j++) \
|
||||
tmp[j] = Conv_ALshort_##T(*(src++)); \
|
||||
EncodeMSADPCMBlock(dst, tmp, sample, index, numchans, align); \
|
||||
dst += byte_align; \
|
||||
} \
|
||||
}
|
||||
|
||||
DECL_TEMPLATE(ALbyte)
|
||||
DECL_TEMPLATE(ALubyte)
|
||||
DECL_TEMPLATE(ALshort)
|
||||
DECL_TEMPLATE(ALushort)
|
||||
DECL_TEMPLATE(ALint)
|
||||
DECL_TEMPLATE(ALuint)
|
||||
DECL_TEMPLATE(ALfloat)
|
||||
DECL_TEMPLATE(ALdouble)
|
||||
DECL_TEMPLATE(ALmulaw)
|
||||
DECL_TEMPLATE(ALalaw)
|
||||
DECL_TEMPLATE(ALbyte3)
|
||||
DECL_TEMPLATE(ALubyte3)
|
||||
|
||||
#undef DECL_TEMPLATE
|
||||
|
||||
/* NOTE: We don't store compressed samples internally, so these conversions
|
||||
* should never happen. */
|
||||
static void Convert_ALima4_ALima4(ALima4* UNUSED(dst), const ALima4* UNUSED(src),
|
||||
ALuint UNUSED(numchans), ALuint UNUSED(len),
|
||||
ALuint UNUSED(align))
|
||||
{
|
||||
ERR("Unexpected IMA4-to-IMA4 conversion!\n");
|
||||
}
|
||||
|
||||
static void Convert_ALmsadpcm_ALmsadpcm(ALmsadpcm* UNUSED(dst), const ALmsadpcm* UNUSED(src),
|
||||
ALuint UNUSED(numchans), ALuint UNUSED(len),
|
||||
ALuint UNUSED(align))
|
||||
{
|
||||
ERR("Unexpected MSADPCM-to-MSADPCM conversion!\n");
|
||||
}
|
||||
|
||||
static void Convert_ALmsadpcm_ALima4(ALmsadpcm* UNUSED(dst), const ALima4* UNUSED(src),
|
||||
ALuint UNUSED(numchans), ALuint UNUSED(len),
|
||||
ALuint UNUSED(align))
|
||||
{
|
||||
ERR("Unexpected IMA4-to-MSADPCM conversion!\n");
|
||||
}
|
||||
|
||||
static void Convert_ALima4_ALmsadpcm(ALima4* UNUSED(dst), const ALmsadpcm* UNUSED(src),
|
||||
ALuint UNUSED(numchans), ALuint UNUSED(len),
|
||||
ALuint UNUSED(align))
|
||||
{
|
||||
ERR("Unexpected MSADPCM-to-IMA4 conversion!\n");
|
||||
}
|
||||
|
||||
|
||||
#define DECL_TEMPLATE(T) \
|
||||
static void Convert_##T(T *dst, const ALvoid *src, enum UserFmtType srcType, \
|
||||
ALsizei numchans, ALsizei len, ALsizei align) \
|
||||
@@ -1780,6 +2039,9 @@ static void Convert_##T(T *dst, const ALvoid *src, enum UserFmtType srcType, \
|
||||
case UserFmtIMA4: \
|
||||
Convert_##T##_ALima4(dst, src, numchans, len, align); \
|
||||
break; \
|
||||
case UserFmtMSADPCM: \
|
||||
Convert_##T##_ALmsadpcm(dst, src, numchans, len, align); \
|
||||
break; \
|
||||
case UserFmtByte3: \
|
||||
Convert_##T##_ALbyte3(dst, src, numchans, len, align); \
|
||||
break; \
|
||||
@@ -1800,6 +2062,7 @@ DECL_TEMPLATE(ALdouble)
|
||||
DECL_TEMPLATE(ALmulaw)
|
||||
DECL_TEMPLATE(ALalaw)
|
||||
DECL_TEMPLATE(ALima4)
|
||||
DECL_TEMPLATE(ALmsadpcm)
|
||||
DECL_TEMPLATE(ALbyte3)
|
||||
DECL_TEMPLATE(ALubyte3)
|
||||
|
||||
@@ -1843,6 +2106,9 @@ static void ConvertData(ALvoid *dst, enum UserFmtType dstType, const ALvoid *src
|
||||
case UserFmtIMA4:
|
||||
Convert_ALima4(dst, src, srcType, numchans, len, align);
|
||||
break;
|
||||
case UserFmtMSADPCM:
|
||||
Convert_ALmsadpcm(dst, src, srcType, numchans, len, align);
|
||||
break;
|
||||
case UserFmtByte3:
|
||||
Convert_ALbyte3(dst, src, srcType, numchans, len, align);
|
||||
break;
|
||||
@@ -1909,6 +2175,12 @@ static ALenum LoadData(ALbuffer *ALBuf, ALuint freq, ALenum NewFormat, ALsizei f
|
||||
ALBuf->OriginalSize = frames / align * byte_align;
|
||||
ALBuf->OriginalAlign = align;
|
||||
}
|
||||
else if(SrcType == UserFmtMSADPCM)
|
||||
{
|
||||
ALsizei byte_align = ((align-2)/2 + 7) * ChannelsFromUserFmt(SrcChannels);
|
||||
ALBuf->OriginalSize = frames / align * byte_align;
|
||||
ALBuf->OriginalAlign = align;
|
||||
}
|
||||
else
|
||||
{
|
||||
ALBuf->OriginalSize = frames * FrameSizeFromUserFmt(SrcChannels, SrcType);
|
||||
@@ -1954,6 +2226,7 @@ ALuint BytesFromUserFmt(enum UserFmtType type)
|
||||
case UserFmtMulaw: return sizeof(ALubyte);
|
||||
case UserFmtAlaw: return sizeof(ALubyte);
|
||||
case UserFmtIMA4: break; /* not handled here */
|
||||
case UserFmtMSADPCM: break; /* not handled here */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -1979,21 +2252,23 @@ static ALboolean DecomposeUserFormat(ALenum format, enum UserFmtChannels *chans,
|
||||
enum UserFmtChannels channels;
|
||||
enum UserFmtType type;
|
||||
} list[] = {
|
||||
{ AL_FORMAT_MONO8, UserFmtMono, UserFmtUByte },
|
||||
{ AL_FORMAT_MONO16, UserFmtMono, UserFmtShort },
|
||||
{ AL_FORMAT_MONO_FLOAT32, UserFmtMono, UserFmtFloat },
|
||||
{ AL_FORMAT_MONO_DOUBLE_EXT, UserFmtMono, UserFmtDouble },
|
||||
{ AL_FORMAT_MONO_IMA4, UserFmtMono, UserFmtIMA4 },
|
||||
{ AL_FORMAT_MONO_MULAW, UserFmtMono, UserFmtMulaw },
|
||||
{ AL_FORMAT_MONO_ALAW_EXT, UserFmtMono, UserFmtAlaw },
|
||||
{ AL_FORMAT_MONO8, UserFmtMono, UserFmtUByte },
|
||||
{ AL_FORMAT_MONO16, UserFmtMono, UserFmtShort },
|
||||
{ AL_FORMAT_MONO_FLOAT32, UserFmtMono, UserFmtFloat },
|
||||
{ AL_FORMAT_MONO_DOUBLE_EXT, UserFmtMono, UserFmtDouble },
|
||||
{ AL_FORMAT_MONO_IMA4, UserFmtMono, UserFmtIMA4 },
|
||||
{ AL_FORMAT_MONO_MSADPCM_SOFT, UserFmtMono, UserFmtMSADPCM },
|
||||
{ AL_FORMAT_MONO_MULAW, UserFmtMono, UserFmtMulaw },
|
||||
{ AL_FORMAT_MONO_ALAW_EXT, UserFmtMono, UserFmtAlaw },
|
||||
|
||||
{ AL_FORMAT_STEREO8, UserFmtStereo, UserFmtUByte },
|
||||
{ AL_FORMAT_STEREO16, UserFmtStereo, UserFmtShort },
|
||||
{ AL_FORMAT_STEREO_FLOAT32, UserFmtStereo, UserFmtFloat },
|
||||
{ AL_FORMAT_STEREO_DOUBLE_EXT, UserFmtStereo, UserFmtDouble },
|
||||
{ AL_FORMAT_STEREO_IMA4, UserFmtStereo, UserFmtIMA4 },
|
||||
{ AL_FORMAT_STEREO_MULAW, UserFmtStereo, UserFmtMulaw },
|
||||
{ AL_FORMAT_STEREO_ALAW_EXT, UserFmtStereo, UserFmtAlaw },
|
||||
{ AL_FORMAT_STEREO8, UserFmtStereo, UserFmtUByte },
|
||||
{ AL_FORMAT_STEREO16, UserFmtStereo, UserFmtShort },
|
||||
{ AL_FORMAT_STEREO_FLOAT32, UserFmtStereo, UserFmtFloat },
|
||||
{ AL_FORMAT_STEREO_DOUBLE_EXT, UserFmtStereo, UserFmtDouble },
|
||||
{ AL_FORMAT_STEREO_IMA4, UserFmtStereo, UserFmtIMA4 },
|
||||
{ AL_FORMAT_STEREO_MSADPCM_SOFT, UserFmtStereo, UserFmtMSADPCM },
|
||||
{ AL_FORMAT_STEREO_MULAW, UserFmtStereo, UserFmtMulaw },
|
||||
{ AL_FORMAT_STEREO_ALAW_EXT, UserFmtStereo, UserFmtAlaw },
|
||||
|
||||
{ AL_FORMAT_REAR8, UserFmtRear, UserFmtUByte },
|
||||
{ AL_FORMAT_REAR16, UserFmtRear, UserFmtShort },
|
||||
@@ -2130,6 +2405,8 @@ static ALboolean SanitizeAlignment(enum UserFmtType type, ALsizei *align)
|
||||
*/
|
||||
*align = 65;
|
||||
}
|
||||
else if(type == UserFmtMSADPCM)
|
||||
*align = 64;
|
||||
else
|
||||
*align = 1;
|
||||
return AL_TRUE;
|
||||
@@ -2138,9 +2415,14 @@ static ALboolean SanitizeAlignment(enum UserFmtType type, ALsizei *align)
|
||||
if(type == UserFmtIMA4)
|
||||
{
|
||||
/* IMA4 block alignment must be a multiple of 8, plus 1. */
|
||||
if(((*align)&7) != 1)
|
||||
return AL_FALSE;
|
||||
return AL_TRUE;
|
||||
return ((*align)&7) == 1;
|
||||
}
|
||||
if(type == UserFmtMSADPCM)
|
||||
{
|
||||
/* MSADPCM block alignment must be a multiple of 8. */
|
||||
/* FIXME: Too strict? Might only require align*channels to be a
|
||||
* multiple of 2. */
|
||||
return ((*align)&7) == 0;
|
||||
}
|
||||
|
||||
return AL_TRUE;
|
||||
|
||||
@@ -2551,6 +2551,23 @@ static ALvoid GetSourceOffsets(const ALsource *Source, ALenum name, ALdouble *of
|
||||
FrameBlockSize * BlockSize);
|
||||
}
|
||||
}
|
||||
else if(Buffer->OriginalType == UserFmtMSADPCM)
|
||||
{
|
||||
ALsizei align = (Buffer->OriginalAlign-2)/2 + 7;
|
||||
ALuint BlockSize = align * ChannelsFromFmt(Buffer->FmtChannels);
|
||||
ALuint FrameBlockSize = Buffer->OriginalAlign;
|
||||
|
||||
/* Round down to nearest ADPCM block */
|
||||
offset[0] = (ALdouble)(readPos / FrameBlockSize * BlockSize);
|
||||
if(Source->state != AL_PLAYING)
|
||||
offset[1] = offset[0];
|
||||
else
|
||||
{
|
||||
/* Round up to nearest ADPCM block */
|
||||
offset[1] = (ALdouble)((writePos+FrameBlockSize-1) /
|
||||
FrameBlockSize * BlockSize);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ALuint FrameSize = FrameSizeFromUserFmt(Buffer->OriginalChannels, Buffer->OriginalType);
|
||||
@@ -2655,6 +2672,12 @@ static ALint GetSampleOffset(ALsource *Source)
|
||||
Offset /= align * ChannelsFromUserFmt(Buffer->OriginalChannels);
|
||||
Offset *= Buffer->OriginalAlign;
|
||||
}
|
||||
else if(Buffer->OriginalType == UserFmtMSADPCM)
|
||||
{
|
||||
ALsizei align = (Buffer->OriginalAlign-2)/2 + 7;
|
||||
Offset /= align * ChannelsFromUserFmt(Buffer->OriginalChannels);
|
||||
Offset *= Buffer->OriginalAlign;
|
||||
}
|
||||
else
|
||||
Offset /= FrameSizeFromUserFmt(Buffer->OriginalChannels, Buffer->OriginalType);
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user