2613 lines
78 KiB
C++
Executable file
2613 lines
78 KiB
C++
Executable file
#include "fmod_settings.h"
|
|
|
|
#include "fmod_dspi.h"
|
|
#include "fmod_dsp_connectioni.h"
|
|
#include "fmod_globals.h"
|
|
#include "fmod_localcriticalsection.h"
|
|
|
|
#ifdef PLATFORM_PS3_SPU
|
|
#include "fmod_systemi_spu.h"
|
|
#else
|
|
#include "fmod_systemi.h"
|
|
#endif
|
|
|
|
namespace FMOD
|
|
{
|
|
|
|
#ifdef FMOD_SUPPORT_SIMD
|
|
extern "C"
|
|
{
|
|
void FMOD_DSP_Connection_MixMonoToStereo_SIMD (float *inbuffer, float *outbuffer, unsigned int length, float lvolume, float rvolume);
|
|
void FMOD_DSP_Connection_MixStereoToStereo_SIMD(float *inbuffer, float *outbuffer, unsigned int length, float lvolume, float rvolume);
|
|
void FMOD_DSP_Connection_MixMonoTo5_1_SIMD (float *inbuffer, float *outbuffer, unsigned int length, float *volume0to3, float *volume4to1, float *volume2to5);
|
|
void FMOD_DSP_Connection_Mix5_1To5_1_SIMD (float *inbuffer, float *outbuffer, unsigned int length, float *volume0to3, float *volume4to1, float *volume2to5);
|
|
void FMOD_DSP_Connection_MixMonoTo7_1_SIMD (float *inbuffer, float *outbuffer, unsigned int length, float *volume0to3, float *volume4to7);
|
|
void FMOD_DSP_Connection_Mix7_1To7_1_SIMD (float *inbuffer, float *outbuffer, unsigned int length, float *volume0to3, float *volume4to7);
|
|
void FMOD_DSP_Connection_MixStereoTo7_1_SIMD (float *inbuffer, float *outbuffer, unsigned int length, float *volume0to3, float *volume01to31, float *volume4to7, float *volume41to71);
|
|
}
|
|
#endif
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT DSPConnectionI::validate(DSPConnection *dspconnection, DSPConnectionI **dspconnectioni)
|
|
{
|
|
if (!dspconnectioni)
|
|
{
|
|
return FMOD_ERR_INVALID_PARAM;
|
|
}
|
|
|
|
if (!dspconnection)
|
|
{
|
|
return FMOD_ERR_INVALID_HANDLE;
|
|
}
|
|
|
|
*dspconnectioni = (DSPConnectionI *)dspconnection;
|
|
|
|
return FMOD_OK;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
FMOD_OK
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT DSPConnectionI::init(DSP_LEVEL_TYPE * &levelmemory, int maxoutputlevels, int maxinputlevels)
|
|
{
|
|
#ifdef FMOD_SUPPORT_SOFTWARE
|
|
mMaxOutputLevels = maxoutputlevels;
|
|
mMaxInputLevels = maxinputlevels;
|
|
|
|
if (maxoutputlevels < 2)
|
|
{
|
|
maxoutputlevels = 2;
|
|
}
|
|
|
|
if (mMaxInputLevels < mMaxOutputLevels)
|
|
{
|
|
mMaxInputLevels = mMaxOutputLevels;
|
|
}
|
|
|
|
#ifdef PLATFORM_PS3_PPU
|
|
mMramAddress = (unsigned int)this;
|
|
mMramAddressLevels = (unsigned int)levelmemory;
|
|
#endif
|
|
|
|
int count;
|
|
for (count = 0; count < DSP_MAXLEVELS_OUT; count++)
|
|
{
|
|
if (count < mMaxOutputLevels)
|
|
{
|
|
mLevel[count] = levelmemory;
|
|
levelmemory += mMaxInputLevels;
|
|
mLevelCurrent[count] = levelmemory;
|
|
levelmemory += mMaxInputLevels;
|
|
mLevelDelta[count] = levelmemory;
|
|
levelmemory += mMaxInputLevels;
|
|
}
|
|
else
|
|
{
|
|
mLevel[count] = 0;
|
|
mLevelCurrent[count] = 0;
|
|
mLevelDelta[count] = 0;
|
|
}
|
|
}
|
|
|
|
return FMOD_OK;
|
|
#else
|
|
return FMOD_ERR_NEEDSSOFTWARE;
|
|
#endif
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT DSPConnectionI::getInput(DSPI **input)
|
|
{
|
|
#ifdef FMOD_SUPPORT_SOFTWARE
|
|
if (!input)
|
|
{
|
|
return FMOD_ERR_INVALID_PARAM;
|
|
}
|
|
|
|
if (!mInputUnit)
|
|
{
|
|
*input = 0;
|
|
return FMOD_ERR_NOTREADY;
|
|
}
|
|
|
|
*input = mInputUnit;
|
|
|
|
return FMOD_OK;
|
|
#else
|
|
return FMOD_ERR_NEEDSSOFTWARE;
|
|
#endif
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT DSPConnectionI::getOutput(DSPI **output)
|
|
{
|
|
if (!output)
|
|
{
|
|
return FMOD_ERR_INVALID_PARAM;
|
|
}
|
|
|
|
if (!mOutputUnit)
|
|
{
|
|
*output = 0;
|
|
return FMOD_ERR_NOTREADY;
|
|
}
|
|
|
|
*output = mOutputUnit;
|
|
|
|
return FMOD_OK;
|
|
}
|
|
|
|
#ifdef FMOD_SUPPORT_SOFTWARE
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
FMOD_OK
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT DSPConnectionI::reset()
|
|
{
|
|
int count, count2;
|
|
|
|
mVolume = 1.0f;
|
|
mUserData = 0;
|
|
mRampCount = 0;
|
|
|
|
for (count = 0; count < mMaxOutputLevels; count++)
|
|
{
|
|
for (count2 = 0; count2 < mMaxInputLevels; count2++)
|
|
{
|
|
mLevel [count][count2] = 0;
|
|
mLevelCurrent[count][count2] = 0;
|
|
mLevelDelta [count][count2] = 0;
|
|
}
|
|
}
|
|
|
|
mSetLevelsUsed = false;
|
|
|
|
return FMOD_OK;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
FMOD_OK
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT DSPConnectionI::setUnity()
|
|
{
|
|
int count, count2;
|
|
|
|
for (count = 0; count < mMaxOutputLevels; count++)
|
|
{
|
|
for (count2 = 0; count2 < mMaxInputLevels; count2++)
|
|
{
|
|
if (count == count2)
|
|
{
|
|
mLevelCurrent[count][count2] = DSP_LEVEL_COMPRESS(1.0f);
|
|
mLevel[count][count2] = DSP_LEVEL_COMPRESS(1.0f);
|
|
}
|
|
else
|
|
{
|
|
mLevel[count][count2] = 0;
|
|
mLevelCurrent[count][count2] = 0;
|
|
}
|
|
}
|
|
}
|
|
mVolume = 1.0f;
|
|
mRampCount = 0;
|
|
|
|
return FMOD_OK;
|
|
}
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
FMOD_OK
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT DSPConnectionI::mix(float * FMOD_RESTRICT outbuffer, float * FMOD_RESTRICT inbuffer, int outchannels, int inchannels, unsigned int length)
|
|
{
|
|
unsigned int count;
|
|
float l00, l10;
|
|
float l01, l11;
|
|
#if (DSP_MAXLEVELS_OUT > 2)
|
|
float l20, l30, l40, l50;
|
|
float l21, l31, l41, l51;
|
|
float l22, l33, l44, l55;
|
|
#endif
|
|
#if (DSP_MAXLEVELS_OUT > 6)
|
|
float l60, l70;
|
|
float l61, l71;
|
|
float l66, l77;
|
|
#endif
|
|
bool supportssimd;
|
|
float levelcurrent[DSP_MAXLEVELS_OUT][DSP_MAXLEVELS_IN] = { 0 };
|
|
|
|
if (!inbuffer)
|
|
{
|
|
return FMOD_OK;
|
|
}
|
|
|
|
supportssimd = FMOD_OS_SupportsSIMD();
|
|
|
|
if (mRampCount)
|
|
{
|
|
unsigned int len = mRampCount;
|
|
|
|
if (len > length)
|
|
{
|
|
len = length;
|
|
}
|
|
|
|
mixAndRamp(outbuffer, inbuffer, outchannels, inchannels, len);
|
|
|
|
length -= len;
|
|
outbuffer += (len * outchannels);
|
|
inbuffer += (len * inchannels);
|
|
}
|
|
|
|
if (!length)
|
|
{
|
|
return FMOD_OK;
|
|
}
|
|
|
|
if (FMOD_FABS(mVolume) < DSP_LEVEL_SMALLVAL)
|
|
{
|
|
return FMOD_OK;
|
|
}
|
|
|
|
for (count = 0; count < (unsigned int)mMaxOutputLevels; count++)
|
|
{
|
|
int count2;
|
|
|
|
if (mLevelCurrent[count])
|
|
{
|
|
for (count2 = 0; count2 < mMaxInputLevels; count2++)
|
|
{
|
|
levelcurrent[count][count2] = DSP_LEVEL_DECOMPRESS(mLevelCurrent[count][count2]);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
Because mLevelCurrent could be misaligned this could hopefully put the values into registers. (confirmed on ps2).
|
|
*/
|
|
|
|
l00 = levelcurrent[0][0];
|
|
l10 = levelcurrent[1][0];
|
|
|
|
#if (DSP_MAXLEVELS_OUT > 2)
|
|
l20 = levelcurrent[2][0];
|
|
l30 = levelcurrent[3][0];
|
|
l40 = levelcurrent[4][0];
|
|
l50 = levelcurrent[5][0];
|
|
#endif
|
|
#if (DSP_MAXLEVELS_OUT > 6)
|
|
l60 = levelcurrent[6][0];
|
|
l70 = levelcurrent[7][0];
|
|
#endif
|
|
|
|
l01 = levelcurrent[0][1];
|
|
l11 = levelcurrent[1][1];
|
|
|
|
#if (DSP_MAXLEVELS_OUT > 2)
|
|
l21 = levelcurrent[2][1];
|
|
l31 = levelcurrent[3][1];
|
|
l41 = levelcurrent[4][1];
|
|
l51 = levelcurrent[5][1];
|
|
|
|
l22 = levelcurrent[2][2];
|
|
l33 = levelcurrent[3][3];
|
|
l44 = levelcurrent[4][4];
|
|
l55 = levelcurrent[5][5];
|
|
#endif
|
|
#if (DSP_MAXLEVELS_OUT > 6)
|
|
l61 = levelcurrent[6][1];
|
|
l71 = levelcurrent[7][1];
|
|
|
|
l66 = levelcurrent[6][6];
|
|
l77 = levelcurrent[7][7];
|
|
#endif
|
|
|
|
/*
|
|
The most common configuration is mono or stereo coming in, and stereo going out, so we special case these for speed.
|
|
Other combinations go through generic for loop code.
|
|
*/
|
|
if (0)
|
|
{
|
|
}
|
|
#if !defined(PLATFORM_PS3_SPU)
|
|
else if (outchannels == 2 && (inchannels == 1 || inchannels == 2))
|
|
{
|
|
if (inchannels == 1)
|
|
{
|
|
#ifdef FMOD_SUPPORT_SIMD
|
|
if (supportssimd)
|
|
{
|
|
/*
|
|
First 16byte align destination for simd.
|
|
*/
|
|
while ((((unsigned int)outbuffer & 0xF) || ((unsigned int)inbuffer & 0xF)) && length)
|
|
{
|
|
outbuffer[0] += (inbuffer[0] * l00);
|
|
outbuffer[1] += (inbuffer[0] * l10);
|
|
inbuffer ++;
|
|
outbuffer += 2;
|
|
length --;
|
|
}
|
|
FMOD_DSP_Connection_MixMonoToStereo_SIMD(inbuffer, outbuffer, length, l00, l10);
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
unsigned int len;
|
|
|
|
len = length >> 2;
|
|
while (len)
|
|
{
|
|
outbuffer[0] += (inbuffer[0] * l00);
|
|
outbuffer[1] += (inbuffer[0] * l10);
|
|
outbuffer[2] += (inbuffer[1] * l00);
|
|
outbuffer[3] += (inbuffer[1] * l10);
|
|
outbuffer[4] += (inbuffer[2] * l00);
|
|
outbuffer[5] += (inbuffer[2] * l10);
|
|
outbuffer[6] += (inbuffer[3] * l00);
|
|
outbuffer[7] += (inbuffer[3] * l10);
|
|
inbuffer += 4;
|
|
outbuffer += 8;
|
|
len --;
|
|
}
|
|
len = length & 3;
|
|
while (len)
|
|
{
|
|
outbuffer[0] += (inbuffer[0] * l00);
|
|
outbuffer[1] += (inbuffer[0] * l10);
|
|
inbuffer ++;
|
|
outbuffer += 2;
|
|
len --;
|
|
}
|
|
}
|
|
}
|
|
else if (inchannels == 2)
|
|
{
|
|
unsigned int len;
|
|
|
|
if (FMOD_FABS(l01) < DSP_LEVEL_SMALLVAL && FMOD_FABS(l10) < DSP_LEVEL_SMALLVAL) /* Pan matrix looks like [l 0] which is the normal way. */
|
|
{ /* [0 r] */
|
|
#ifdef FMOD_SUPPORT_SIMD
|
|
if (supportssimd)
|
|
{
|
|
/*
|
|
First 16byte align destination for simd.
|
|
*/
|
|
while ((unsigned int)outbuffer & 0xF && length)
|
|
{
|
|
outbuffer[0] += (inbuffer[0] * l00);
|
|
outbuffer[1] += (inbuffer[1] * l11);
|
|
inbuffer += 2;
|
|
outbuffer += 2;
|
|
length --;
|
|
}
|
|
FMOD_DSP_Connection_MixStereoToStereo_SIMD(inbuffer, outbuffer, length, l00, l11);
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
len = length >> 2;
|
|
while (len)
|
|
{
|
|
outbuffer[0] += (inbuffer[0] * l00);
|
|
outbuffer[1] += (inbuffer[1] * l11);
|
|
|
|
outbuffer[2] += (inbuffer[2] * l00);
|
|
outbuffer[3] += (inbuffer[3] * l11);
|
|
|
|
outbuffer[4] += (inbuffer[4] * l00);
|
|
outbuffer[5] += (inbuffer[5] * l11);
|
|
|
|
outbuffer[6] += (inbuffer[6] * l00);
|
|
outbuffer[7] += (inbuffer[7] * l11);
|
|
inbuffer += 8;
|
|
outbuffer += 8;
|
|
len --;
|
|
}
|
|
|
|
len = length & 3;
|
|
while (len)
|
|
{
|
|
outbuffer[0] += (inbuffer[0] * l00);
|
|
outbuffer[1] += (inbuffer[1] * l11);
|
|
inbuffer += 2;
|
|
outbuffer += 2;
|
|
len --;
|
|
}
|
|
}
|
|
}
|
|
else /* Pan matrix looks like [l ?] must have used setSpeakerMix. */
|
|
{ /* [? r] */
|
|
len = length >> 2;
|
|
while (len)
|
|
{
|
|
outbuffer[0] += (inbuffer[0] * l00);
|
|
outbuffer[0] += (inbuffer[1] * l01);
|
|
outbuffer[1] += (inbuffer[0] * l10);
|
|
outbuffer[1] += (inbuffer[1] * l11);
|
|
|
|
outbuffer[2] += (inbuffer[2] * l00);
|
|
outbuffer[2] += (inbuffer[3] * l01);
|
|
outbuffer[3] += (inbuffer[2] * l10);
|
|
outbuffer[3] += (inbuffer[3] * l11);
|
|
|
|
outbuffer[4] += (inbuffer[4] * l00);
|
|
outbuffer[4] += (inbuffer[5] * l01);
|
|
outbuffer[5] += (inbuffer[4] * l10);
|
|
outbuffer[5] += (inbuffer[5] * l11);
|
|
|
|
outbuffer[6] += (inbuffer[6] * l00);
|
|
outbuffer[6] += (inbuffer[7] * l01);
|
|
outbuffer[7] += (inbuffer[6] * l10);
|
|
outbuffer[7] += (inbuffer[7] * l11);
|
|
inbuffer += 8;
|
|
outbuffer += 8;
|
|
len --;
|
|
}
|
|
|
|
len = length & 3;
|
|
while (len)
|
|
{
|
|
outbuffer[0] += (inbuffer[0] * l00);
|
|
outbuffer[0] += (inbuffer[1] * l01);
|
|
outbuffer[1] += (inbuffer[0] * l10);
|
|
outbuffer[1] += (inbuffer[1] * l11);
|
|
inbuffer += 2;
|
|
outbuffer += 2;
|
|
len --;
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
#if (DSP_MAXLEVELS_OUT > 2) && !defined(PLATFORM_PS3_PPU)
|
|
else if (outchannels == 6 && (inchannels == 1 || inchannels == 2 || inchannels == 6))//(inchannels == 6 && checkUnity(outchannels, inchannels) == FMOD_OK)))
|
|
{
|
|
if (inchannels == 1)
|
|
{
|
|
#ifdef FMOD_SUPPORT_SIMD
|
|
if (supportssimd)
|
|
{
|
|
float volume0to3[4] = { l00, l10, l20, l30 };
|
|
float volume4to1[4] = { l40, l50, l00, l10 };
|
|
float volume2to5[4] = { l20, l30, l40, l50 };
|
|
|
|
/*
|
|
First 16byte align destination for simd.
|
|
*/
|
|
while ((unsigned int)outbuffer & 0xF && length)
|
|
{
|
|
outbuffer[0] += (inbuffer[0] * l00);
|
|
outbuffer[1] += (inbuffer[0] * l10);
|
|
outbuffer[2] += (inbuffer[0] * l20);
|
|
outbuffer[3] += (inbuffer[0] * l30);
|
|
outbuffer[4] += (inbuffer[0] * l40);
|
|
outbuffer[5] += (inbuffer[0] * l50);
|
|
|
|
inbuffer ++;
|
|
outbuffer +=6;
|
|
length --;
|
|
}
|
|
|
|
FMOD_DSP_Connection_MixMonoTo5_1_SIMD(inbuffer, outbuffer, length, volume0to3, volume4to1, volume2to5);
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
unsigned int len;
|
|
|
|
len = length >> 2;
|
|
while (len)
|
|
{
|
|
outbuffer[0] += (inbuffer[0] * l00);
|
|
outbuffer[1] += (inbuffer[0] * l10);
|
|
outbuffer[2] += (inbuffer[0] * l20);
|
|
outbuffer[3] += (inbuffer[0] * l30);
|
|
|
|
outbuffer[4] += (inbuffer[0] * l40);
|
|
outbuffer[5] += (inbuffer[0] * l50);
|
|
outbuffer[6] += (inbuffer[1] * l00);
|
|
outbuffer[7] += (inbuffer[1] * l10);
|
|
|
|
outbuffer[8] += (inbuffer[1] * l20);
|
|
outbuffer[9] += (inbuffer[1] * l30);
|
|
outbuffer[10] += (inbuffer[1] * l40);
|
|
outbuffer[11] += (inbuffer[1] * l50);
|
|
|
|
outbuffer[12] += (inbuffer[2] * l00);
|
|
outbuffer[13] += (inbuffer[2] * l10);
|
|
outbuffer[14] += (inbuffer[2] * l20);
|
|
outbuffer[15] += (inbuffer[2] * l30);
|
|
|
|
outbuffer[16] += (inbuffer[2] * l40);
|
|
outbuffer[17] += (inbuffer[2] * l50);
|
|
outbuffer[18] += (inbuffer[3] * l00);
|
|
outbuffer[19] += (inbuffer[3] * l10);
|
|
|
|
outbuffer[20] += (inbuffer[3] * l20);
|
|
outbuffer[21] += (inbuffer[3] * l30);
|
|
outbuffer[22] += (inbuffer[3] * l40);
|
|
outbuffer[23] += (inbuffer[3] * l50);
|
|
|
|
outbuffer += 24;
|
|
inbuffer += 4;
|
|
|
|
len--;
|
|
}
|
|
|
|
len = length & 3;
|
|
if (len)
|
|
{
|
|
while (len)
|
|
{
|
|
outbuffer[0] += (inbuffer[0] * l00);
|
|
outbuffer[1] += (inbuffer[0] * l10);
|
|
outbuffer[2] += (inbuffer[0] * l20);
|
|
outbuffer[3] += (inbuffer[0] * l30);
|
|
outbuffer[4] += (inbuffer[0] * l40);
|
|
outbuffer[5] += (inbuffer[0] * l50);
|
|
|
|
inbuffer ++;
|
|
outbuffer +=6;
|
|
len --;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (inchannels == 2)
|
|
{
|
|
unsigned int len;
|
|
|
|
/* Pan matrix looks like [l 0] which is the normal way. */
|
|
/* [0 r] */
|
|
/* [0 0] */
|
|
/* [0 0] */
|
|
/* [0 0] */
|
|
/* [0 0] */
|
|
if (FMOD_FABS(l01) < DSP_LEVEL_SMALLVAL && FMOD_FABS(l10) < DSP_LEVEL_SMALLVAL &&
|
|
FMOD_FABS(l20) < DSP_LEVEL_SMALLVAL && FMOD_FABS(l21) < DSP_LEVEL_SMALLVAL &&
|
|
FMOD_FABS(l30) < DSP_LEVEL_SMALLVAL && FMOD_FABS(l31) < DSP_LEVEL_SMALLVAL &&
|
|
FMOD_FABS(l40) < DSP_LEVEL_SMALLVAL && FMOD_FABS(l41) < DSP_LEVEL_SMALLVAL &&
|
|
FMOD_FABS(l50) < DSP_LEVEL_SMALLVAL && FMOD_FABS(l51) < DSP_LEVEL_SMALLVAL)
|
|
{
|
|
len = length >> 2;
|
|
while (len)
|
|
{
|
|
outbuffer[0] += (inbuffer[0] * l00);
|
|
outbuffer[1] += (inbuffer[1] * l11);
|
|
// outbuffer[2 += 0;
|
|
// outbuffer[3] += 0;
|
|
// outbuffer[4] += 0;
|
|
// outbuffer[5] += 0;
|
|
|
|
outbuffer[6] += (inbuffer[2] * l00);
|
|
outbuffer[7] += (inbuffer[3] * l11);
|
|
// outbuffer[8] += 0;
|
|
// outbuffer[9] += 0;
|
|
// outbuffer[10] += 0;
|
|
// outbuffer[11] += 0;
|
|
|
|
outbuffer[12] += (inbuffer[4] * l00);
|
|
outbuffer[13] += (inbuffer[5] * l11);
|
|
// outbuffer[14] += 0;
|
|
// outbuffer[15] += 0;
|
|
// outbuffer[16] += 0;
|
|
// outbuffer[17] += 0;
|
|
|
|
outbuffer[18] += (inbuffer[6] * l00);
|
|
outbuffer[19] += (inbuffer[7] * l11);
|
|
// outbuffer[20] += 0;
|
|
// outbuffer[21] += 0;
|
|
// outbuffer[22] += 0;
|
|
// outbuffer[23] += 0;
|
|
|
|
outbuffer += 24;
|
|
inbuffer += 8;
|
|
len--;
|
|
}
|
|
|
|
len = length & 3;
|
|
if (len)
|
|
{
|
|
while (len)
|
|
{
|
|
outbuffer[0] += (inbuffer[0] * l00);
|
|
outbuffer[1] += (inbuffer[1] * l11);
|
|
//outbuffer[2] += 0;
|
|
//outbuffer[3] += 0;
|
|
//outbuffer[4] += 0;
|
|
//outbuffer[5] += 0;
|
|
|
|
inbuffer += 2;
|
|
outbuffer += 6;
|
|
len --;
|
|
}
|
|
}
|
|
}
|
|
else /* Pan matrix looks like [l ?] must have used setSpeakerMix. */
|
|
{ /* [? r] */
|
|
len = length >> 1;
|
|
while (len)
|
|
{
|
|
outbuffer[0] += (inbuffer[0] * l00);
|
|
outbuffer[0] += (inbuffer[1] * l01);
|
|
outbuffer[1] += (inbuffer[0] * l10);
|
|
outbuffer[1] += (inbuffer[1] * l11);
|
|
outbuffer[2] += (inbuffer[0] * l20);
|
|
outbuffer[2] += (inbuffer[1] * l21);
|
|
outbuffer[3] += (inbuffer[0] * l30);
|
|
outbuffer[3] += (inbuffer[1] * l31);
|
|
outbuffer[4] += (inbuffer[0] * l40);
|
|
outbuffer[4] += (inbuffer[1] * l41);
|
|
outbuffer[5] += (inbuffer[0] * l50);
|
|
outbuffer[5] += (inbuffer[1] * l51);
|
|
|
|
outbuffer[6] += (inbuffer[2] * l00);
|
|
outbuffer[6] += (inbuffer[3] * l01);
|
|
outbuffer[7] += (inbuffer[2] * l10);
|
|
outbuffer[7] += (inbuffer[3] * l11);
|
|
outbuffer[8] += (inbuffer[2] * l20);
|
|
outbuffer[8] += (inbuffer[3] * l21);
|
|
outbuffer[9] += (inbuffer[2] * l30);
|
|
outbuffer[9] += (inbuffer[3] * l31);
|
|
outbuffer[10] += (inbuffer[2] * l40);
|
|
outbuffer[10] += (inbuffer[3] * l41);
|
|
outbuffer[11] += (inbuffer[2] * l50);
|
|
outbuffer[11] += (inbuffer[3] * l51);
|
|
|
|
inbuffer += 4;
|
|
outbuffer += 12;
|
|
len --;
|
|
}
|
|
|
|
len = length & 1;
|
|
while (len)
|
|
{
|
|
outbuffer[0] += (inbuffer[0] * l00);
|
|
outbuffer[0] += (inbuffer[1] * l01);
|
|
outbuffer[1] += (inbuffer[0] * l10);
|
|
outbuffer[1] += (inbuffer[1] * l11);
|
|
outbuffer[2] += (inbuffer[0] * l20);
|
|
outbuffer[2] += (inbuffer[1] * l21);
|
|
outbuffer[3] += (inbuffer[0] * l30);
|
|
outbuffer[3] += (inbuffer[1] * l31);
|
|
outbuffer[4] += (inbuffer[0] * l40);
|
|
outbuffer[4] += (inbuffer[1] * l41);
|
|
outbuffer[5] += (inbuffer[0] * l50);
|
|
outbuffer[5] += (inbuffer[1] * l51);
|
|
|
|
inbuffer += 2;
|
|
outbuffer += 6;
|
|
len --;
|
|
}
|
|
}
|
|
}
|
|
else if (inchannels == 6)
|
|
{
|
|
FMOD_RESULT unity = checkUnity(outchannels, inchannels);
|
|
FMOD_RESULT mono = FMOD_ERR_TOOMANYCHANNELS;
|
|
|
|
if (unity != FMOD_OK)
|
|
{
|
|
mono = checkMono(outchannels, inchannels);
|
|
}
|
|
|
|
if (unity == FMOD_OK || mono == FMOD_OK)
|
|
{
|
|
float l[6];
|
|
|
|
if (unity == FMOD_OK)
|
|
{
|
|
l[0] = l00;
|
|
l[1] = l11;
|
|
l[2] = l22;
|
|
l[3] = l33;
|
|
l[4] = l44;
|
|
l[5] = l55;
|
|
}
|
|
else
|
|
{
|
|
l[0] = l00;
|
|
l[1] = l10;
|
|
l[2] = l20;
|
|
l[3] = l30;
|
|
l[4] = l40;
|
|
l[5] = l50;
|
|
}
|
|
|
|
#ifdef FMOD_SUPPORT_SIMD
|
|
if (supportssimd)
|
|
{
|
|
float volume0to3[4] = { l[0], l[1], l[2], l[3] };
|
|
float volume4to1[4] = { l[4], l[5], l[0], l[1] };
|
|
float volume2to5[4] = { l[2], l[3], l[4], l[5] };
|
|
|
|
/*
|
|
First 16byte align destination for simd.
|
|
*/
|
|
while ((unsigned int)outbuffer & 0xF && length)
|
|
{
|
|
outbuffer[0] += (inbuffer[0] * l[0]);
|
|
outbuffer[1] += (inbuffer[1] * l[1]);
|
|
outbuffer[2] += (inbuffer[2] * l[2]);
|
|
outbuffer[3] += (inbuffer[3] * l[3]);
|
|
outbuffer[4] += (inbuffer[4] * l[4]);
|
|
outbuffer[5] += (inbuffer[5] * l[5]);
|
|
|
|
inbuffer +=6;
|
|
outbuffer +=6;
|
|
length --;
|
|
}
|
|
|
|
FMOD_DSP_Connection_Mix5_1To5_1_SIMD(inbuffer, outbuffer, length, volume0to3, volume4to1, volume2to5);
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
unsigned int len;
|
|
|
|
len = length >> 2;
|
|
while (len)
|
|
{
|
|
outbuffer[0] += (inbuffer[0] * l[0]);
|
|
outbuffer[1] += (inbuffer[1] * l[1]);
|
|
outbuffer[2] += (inbuffer[2] * l[2]);
|
|
outbuffer[3] += (inbuffer[3] * l[3]);
|
|
outbuffer[4] += (inbuffer[4] * l[4]);
|
|
outbuffer[5] += (inbuffer[5] * l[5]);
|
|
outbuffer[6] += (inbuffer[6] * l[0]);
|
|
outbuffer[7] += (inbuffer[7] * l[1]);
|
|
outbuffer[8] += (inbuffer[8] * l[2]);
|
|
outbuffer[9] += (inbuffer[9] * l[3]);
|
|
outbuffer[10] += (inbuffer[10] * l[4]);
|
|
outbuffer[11] += (inbuffer[11] * l[5]);
|
|
|
|
outbuffer[12] += (inbuffer[12] * l[0]);
|
|
outbuffer[13] += (inbuffer[13] * l[1]);
|
|
outbuffer[14] += (inbuffer[14] * l[2]);
|
|
outbuffer[15] += (inbuffer[15] * l[3]);
|
|
outbuffer[16] += (inbuffer[16] * l[4]);
|
|
outbuffer[17] += (inbuffer[17] * l[5]);
|
|
outbuffer[18] += (inbuffer[18] * l[0]);
|
|
outbuffer[19] += (inbuffer[19] * l[1]);
|
|
outbuffer[20] += (inbuffer[20] * l[2]);
|
|
outbuffer[21] += (inbuffer[21] * l[3]);
|
|
outbuffer[22] += (inbuffer[22] * l[4]);
|
|
outbuffer[23] += (inbuffer[23] * l[5]);
|
|
|
|
outbuffer += 24;
|
|
inbuffer += 24;
|
|
len--;
|
|
}
|
|
|
|
len = length & 3;
|
|
if (len)
|
|
{
|
|
while (len)
|
|
{
|
|
outbuffer[0] += (inbuffer[0] * l[0]);
|
|
outbuffer[1] += (inbuffer[1] * l[1]);
|
|
outbuffer[2] += (inbuffer[2] * l[2]);
|
|
outbuffer[3] += (inbuffer[3] * l[3]);
|
|
outbuffer[4] += (inbuffer[4] * l[4]);
|
|
outbuffer[5] += (inbuffer[5] * l[5]);
|
|
|
|
inbuffer +=6;
|
|
outbuffer +=6;
|
|
len --;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
#if 0
|
|
for (count = 0; count < length; count++)
|
|
{
|
|
int count2;
|
|
|
|
for (count2 = 0; count2 < outchannels; count2++)
|
|
{
|
|
float srcval = 0;
|
|
float destval = *outbuffer;
|
|
int count3;
|
|
|
|
for (count3 = 0; count3 < inchannels; count3++)
|
|
{
|
|
srcval += (inbuffer[count3] * levelcurrent[count2][count3]);
|
|
}
|
|
|
|
destval += srcval;
|
|
*outbuffer++ = destval;
|
|
}
|
|
|
|
inbuffer += inchannels;
|
|
}
|
|
#else
|
|
for (count = 0; count < length; count++)
|
|
{
|
|
float srcval;
|
|
|
|
srcval = (inbuffer[0] * levelcurrent[0][0]);
|
|
srcval += (inbuffer[1] * levelcurrent[0][1]);
|
|
srcval += (inbuffer[2] * levelcurrent[0][2]);
|
|
srcval += (inbuffer[3] * levelcurrent[0][3]);
|
|
srcval += (inbuffer[4] * levelcurrent[0][4]);
|
|
srcval += (inbuffer[5] * levelcurrent[0][5]);
|
|
outbuffer[0] += srcval;
|
|
|
|
srcval = (inbuffer[0] * levelcurrent[1][0]);
|
|
srcval += (inbuffer[1] * levelcurrent[1][1]);
|
|
srcval += (inbuffer[2] * levelcurrent[1][2]);
|
|
srcval += (inbuffer[3] * levelcurrent[1][3]);
|
|
srcval += (inbuffer[4] * levelcurrent[1][4]);
|
|
srcval += (inbuffer[5] * levelcurrent[1][5]);
|
|
outbuffer[1] += srcval;
|
|
|
|
srcval = (inbuffer[0] * levelcurrent[2][0]);
|
|
srcval += (inbuffer[1] * levelcurrent[2][1]);
|
|
srcval += (inbuffer[2] * levelcurrent[2][2]);
|
|
srcval += (inbuffer[3] * levelcurrent[2][3]);
|
|
srcval += (inbuffer[4] * levelcurrent[2][4]);
|
|
srcval += (inbuffer[5] * levelcurrent[2][5]);
|
|
outbuffer[2] += srcval;
|
|
|
|
srcval = (inbuffer[0] * levelcurrent[3][0]);
|
|
srcval += (inbuffer[1] * levelcurrent[3][1]);
|
|
srcval += (inbuffer[2] * levelcurrent[3][2]);
|
|
srcval += (inbuffer[3] * levelcurrent[3][3]);
|
|
srcval += (inbuffer[4] * levelcurrent[3][4]);
|
|
srcval += (inbuffer[5] * levelcurrent[3][5]);
|
|
outbuffer[3] += srcval;
|
|
|
|
srcval = (inbuffer[0] * levelcurrent[4][0]);
|
|
srcval += (inbuffer[1] * levelcurrent[4][1]);
|
|
srcval += (inbuffer[2] * levelcurrent[4][2]);
|
|
srcval += (inbuffer[3] * levelcurrent[4][3]);
|
|
srcval += (inbuffer[4] * levelcurrent[4][4]);
|
|
srcval += (inbuffer[5] * levelcurrent[4][5]);
|
|
outbuffer[4] += srcval;
|
|
|
|
srcval = (inbuffer[0] * levelcurrent[5][0]);
|
|
srcval += (inbuffer[1] * levelcurrent[5][1]);
|
|
srcval += (inbuffer[2] * levelcurrent[5][2]);
|
|
srcval += (inbuffer[3] * levelcurrent[5][3]);
|
|
srcval += (inbuffer[4] * levelcurrent[5][4]);
|
|
srcval += (inbuffer[5] * levelcurrent[5][5]);
|
|
outbuffer[5] += srcval;
|
|
|
|
outbuffer += 6;
|
|
inbuffer += 6;
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
#endif /* #if (DSP_MAXLEVELS_OUT != 8) */
|
|
|
|
#if (DSP_MAXLEVELS_OUT > 6) && !defined(PLATFORM_PS3_PPU)
|
|
else if (outchannels == 8 && (inchannels == 1 || inchannels == 2 || inchannels == 8)) // && checkUnity(outchannels, inchannels) == FMOD_OK)))
|
|
{
|
|
if (inchannels == 1)
|
|
{
|
|
#ifdef FMOD_SUPPORT_SIMD
|
|
if (supportssimd)
|
|
{
|
|
float volume0to3[4] = { l00, l10, l20, l30 };
|
|
float volume4to7[4] = { l40, l50, l60, l70 };
|
|
|
|
FMOD_DSP_Connection_MixMonoTo7_1_SIMD(inbuffer, outbuffer, length, volume0to3, volume4to7);
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
unsigned int len;
|
|
|
|
len = length >> 1;
|
|
while (len)
|
|
{
|
|
outbuffer[0] += (inbuffer[0] * l00);
|
|
outbuffer[1] += (inbuffer[0] * l10);
|
|
outbuffer[2] += (inbuffer[0] * l20);
|
|
outbuffer[3] += (inbuffer[0] * l30);
|
|
outbuffer[4] += (inbuffer[0] * l40);
|
|
outbuffer[5] += (inbuffer[0] * l50);
|
|
outbuffer[6] += (inbuffer[0] * l60);
|
|
outbuffer[7] += (inbuffer[0] * l70);
|
|
|
|
outbuffer[8] += (inbuffer[1] * l00);
|
|
outbuffer[9] += (inbuffer[1] * l10);
|
|
outbuffer[10] += (inbuffer[1] * l20);
|
|
outbuffer[11] += (inbuffer[1] * l30);
|
|
outbuffer[12] += (inbuffer[1] * l40);
|
|
outbuffer[13] += (inbuffer[1] * l50);
|
|
outbuffer[14] += (inbuffer[1] * l60);
|
|
outbuffer[15] += (inbuffer[1] * l70);
|
|
|
|
outbuffer += 16;
|
|
inbuffer += 2;
|
|
|
|
len--;
|
|
}
|
|
|
|
len = length & 1;
|
|
if (len)
|
|
{
|
|
while (len)
|
|
{
|
|
outbuffer[0] += (inbuffer[0] * l00);
|
|
outbuffer[1] += (inbuffer[0] * l10);
|
|
outbuffer[2] += (inbuffer[0] * l20);
|
|
outbuffer[3] += (inbuffer[0] * l30);
|
|
outbuffer[4] += (inbuffer[0] * l40);
|
|
outbuffer[5] += (inbuffer[0] * l50);
|
|
outbuffer[6] += (inbuffer[0] * l60);
|
|
outbuffer[7] += (inbuffer[0] * l70);
|
|
|
|
inbuffer ++;
|
|
outbuffer +=8;
|
|
len --;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (inchannels == 2)
|
|
{
|
|
unsigned int len;
|
|
|
|
/* Pan matrix looks like [l 0] which is the normal way. */
|
|
/* [0 r] */
|
|
/* [0 0] */
|
|
/* [0 0] */
|
|
/* [0 0] */
|
|
/* [0 0] */
|
|
if (FMOD_FABS(l01) < DSP_LEVEL_SMALLVAL && FMOD_FABS(l10) < DSP_LEVEL_SMALLVAL &&
|
|
FMOD_FABS(l20) < DSP_LEVEL_SMALLVAL && FMOD_FABS(l21) < DSP_LEVEL_SMALLVAL &&
|
|
FMOD_FABS(l30) < DSP_LEVEL_SMALLVAL && FMOD_FABS(l31) < DSP_LEVEL_SMALLVAL &&
|
|
FMOD_FABS(l40) < DSP_LEVEL_SMALLVAL && FMOD_FABS(l41) < DSP_LEVEL_SMALLVAL &&
|
|
FMOD_FABS(l50) < DSP_LEVEL_SMALLVAL && FMOD_FABS(l51) < DSP_LEVEL_SMALLVAL &&
|
|
FMOD_FABS(l60) < DSP_LEVEL_SMALLVAL && FMOD_FABS(l61) < DSP_LEVEL_SMALLVAL &&
|
|
FMOD_FABS(l70) < DSP_LEVEL_SMALLVAL && FMOD_FABS(l71) < DSP_LEVEL_SMALLVAL)
|
|
{
|
|
len = length >> 2;
|
|
while (len)
|
|
{
|
|
outbuffer[0] += (inbuffer[0] * l00);
|
|
outbuffer[1] += (inbuffer[1] * l11);
|
|
// outbuffer[2 += 0;
|
|
// outbuffer[3] += 0;
|
|
// outbuffer[4] += 0;
|
|
// outbuffer[5] += 0;
|
|
// outbuffer[6] += 0;
|
|
// outbuffer[7] += 0;
|
|
|
|
outbuffer[8] += (inbuffer[2] * l00);
|
|
outbuffer[9] += (inbuffer[3] * l11);
|
|
// outbuffer[10] += 0;
|
|
// outbuffer[11] += 0;
|
|
// outbuffer[12] += 0;
|
|
// outbuffer[13] += 0;
|
|
// outbuffer[14] += 0;
|
|
// outbuffer[15] += 0;
|
|
|
|
outbuffer[16] += (inbuffer[4] * l00);
|
|
outbuffer[17] += (inbuffer[5] * l11);
|
|
// outbuffer[18] += 0;
|
|
// outbuffer[19] += 0;
|
|
// outbuffer[20] += 0;
|
|
// outbuffer[21] += 0;
|
|
// outbuffer[22] += 0;
|
|
// outbuffer[23] += 0;
|
|
|
|
outbuffer[24] += (inbuffer[6] * l00);
|
|
outbuffer[25] += (inbuffer[7] * l11);
|
|
// outbuffer[26] += 0;
|
|
// outbuffer[27] += 0;
|
|
// outbuffer[28] += 0;
|
|
// outbuffer[29] += 0;
|
|
// outbuffer[30] += 0;
|
|
// outbuffer[31] += 0;
|
|
|
|
outbuffer += 32;
|
|
inbuffer += 8;
|
|
len--;
|
|
}
|
|
|
|
len = length & 3;
|
|
if (len)
|
|
{
|
|
while (len)
|
|
{
|
|
outbuffer[0] += (inbuffer[0] * l00);
|
|
outbuffer[1] += (inbuffer[1] * l11);
|
|
//outbuffer[2] += 0;
|
|
//outbuffer[3] += 0;
|
|
//outbuffer[4] += 0;
|
|
//outbuffer[5] += 0;
|
|
//outbuffer[6] += 0;
|
|
//outbuffer[7] += 0;
|
|
|
|
inbuffer += 2;
|
|
outbuffer += 8;
|
|
len --;
|
|
}
|
|
}
|
|
}
|
|
else /* Pan matrix looks like [l ?] must have used setSpeakerMix. */
|
|
{ /* [? r] */
|
|
#ifdef PLATFORM_XENON
|
|
float volume0to3[4] = { l00, l10, l20, l30 };
|
|
float volume01to31[4] = { l01, l11, l21, l31 };
|
|
float volume4to7[4] = { l40, l50, l60, l70 };
|
|
float volume41to71[4] = { l41, l51, l61, l71 };
|
|
|
|
FMOD_DSP_Connection_MixStereoTo7_1_SIMD(inbuffer, outbuffer, length, volume0to3, volume01to31, volume4to7, volume41to71);
|
|
#else
|
|
len = length >> 1;
|
|
while (len)
|
|
{
|
|
outbuffer[0] += (inbuffer[0] * l00);
|
|
outbuffer[0] += (inbuffer[1] * l01);
|
|
outbuffer[1] += (inbuffer[0] * l10);
|
|
outbuffer[1] += (inbuffer[1] * l11);
|
|
outbuffer[2] += (inbuffer[0] * l20);
|
|
outbuffer[2] += (inbuffer[1] * l21);
|
|
outbuffer[3] += (inbuffer[0] * l30);
|
|
outbuffer[3] += (inbuffer[1] * l31);
|
|
outbuffer[4] += (inbuffer[0] * l40);
|
|
outbuffer[4] += (inbuffer[1] * l41);
|
|
outbuffer[5] += (inbuffer[0] * l50);
|
|
outbuffer[5] += (inbuffer[1] * l51);
|
|
outbuffer[6] += (inbuffer[0] * l60);
|
|
outbuffer[6] += (inbuffer[1] * l61);
|
|
outbuffer[7] += (inbuffer[0] * l70);
|
|
outbuffer[7] += (inbuffer[1] * l71);
|
|
|
|
outbuffer[8] += (inbuffer[2] * l00);
|
|
outbuffer[8] += (inbuffer[3] * l01);
|
|
outbuffer[9] += (inbuffer[2] * l10);
|
|
outbuffer[9] += (inbuffer[3] * l11);
|
|
outbuffer[10] += (inbuffer[2] * l20);
|
|
outbuffer[10] += (inbuffer[3] * l21);
|
|
outbuffer[11] += (inbuffer[2] * l30);
|
|
outbuffer[11] += (inbuffer[3] * l31);
|
|
outbuffer[12] += (inbuffer[2] * l40);
|
|
outbuffer[12] += (inbuffer[3] * l41);
|
|
outbuffer[13] += (inbuffer[2] * l50);
|
|
outbuffer[13] += (inbuffer[3] * l51);
|
|
outbuffer[14] += (inbuffer[2] * l60);
|
|
outbuffer[14] += (inbuffer[3] * l61);
|
|
outbuffer[15] += (inbuffer[2] * l70);
|
|
outbuffer[15] += (inbuffer[3] * l71);
|
|
|
|
inbuffer += 4;
|
|
outbuffer += 16;
|
|
len --;
|
|
}
|
|
#endif
|
|
|
|
len = length & 1;
|
|
while (len)
|
|
{
|
|
outbuffer[0] += (inbuffer[0] * l00);
|
|
outbuffer[0] += (inbuffer[1] * l01);
|
|
outbuffer[1] += (inbuffer[0] * l10);
|
|
outbuffer[1] += (inbuffer[1] * l11);
|
|
outbuffer[2] += (inbuffer[0] * l20);
|
|
outbuffer[2] += (inbuffer[1] * l21);
|
|
outbuffer[3] += (inbuffer[0] * l30);
|
|
outbuffer[3] += (inbuffer[1] * l31);
|
|
outbuffer[4] += (inbuffer[0] * l40);
|
|
outbuffer[4] += (inbuffer[1] * l41);
|
|
outbuffer[5] += (inbuffer[0] * l50);
|
|
outbuffer[5] += (inbuffer[1] * l51);
|
|
outbuffer[6] += (inbuffer[0] * l60);
|
|
outbuffer[6] += (inbuffer[1] * l61);
|
|
outbuffer[7] += (inbuffer[0] * l70);
|
|
outbuffer[7] += (inbuffer[1] * l71);
|
|
|
|
inbuffer += 2;
|
|
outbuffer += 8;
|
|
len --;
|
|
}
|
|
}
|
|
}
|
|
else if (inchannels == 8)
|
|
{
|
|
#if 0
|
|
if (mUnity)
|
|
{
|
|
mUnity = mUnity;
|
|
}
|
|
else
|
|
#endif
|
|
FMOD_RESULT unity = checkUnity(outchannels, inchannels);
|
|
FMOD_RESULT mono = FMOD_ERR_TOOMANYCHANNELS;
|
|
|
|
if (unity != FMOD_OK)
|
|
{
|
|
mono = checkMono(outchannels, inchannels);
|
|
}
|
|
|
|
if (unity == FMOD_OK || mono == FMOD_OK)
|
|
{
|
|
float l[8];
|
|
|
|
if (unity == FMOD_OK)
|
|
{
|
|
l[0] = l00;
|
|
l[1] = l11;
|
|
l[2] = l22;
|
|
l[3] = l33;
|
|
l[4] = l44;
|
|
l[5] = l55;
|
|
l[6] = l66;
|
|
l[7] = l77;
|
|
}
|
|
else
|
|
{
|
|
l[0] = l00;
|
|
l[1] = l10;
|
|
l[2] = l20;
|
|
l[3] = l30;
|
|
l[4] = l40;
|
|
l[5] = l50;
|
|
l[6] = l60;
|
|
l[7] = l70;
|
|
}
|
|
|
|
#ifdef FMOD_SUPPORT_SIMD
|
|
if (supportssimd)
|
|
{
|
|
float volume0to3[4] = { l[0], l[1], l[2], l[3] };
|
|
float volume4to7[4] = { l[4], l[5], l[6], l[7] };
|
|
|
|
FMOD_DSP_Connection_Mix7_1To7_1_SIMD(inbuffer, outbuffer, length, volume0to3, volume4to7);
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
unsigned int len;
|
|
|
|
len = length >> 1;
|
|
while (len)
|
|
{
|
|
outbuffer[0] += (inbuffer[0] * l[0]);
|
|
outbuffer[1] += (inbuffer[1] * l[1]);
|
|
outbuffer[2] += (inbuffer[2] * l[2]);
|
|
outbuffer[3] += (inbuffer[3] * l[3]);
|
|
outbuffer[4] += (inbuffer[4] * l[4]);
|
|
outbuffer[5] += (inbuffer[5] * l[5]);
|
|
outbuffer[6] += (inbuffer[6] * l[6]);
|
|
outbuffer[7] += (inbuffer[7] * l[7]);
|
|
|
|
outbuffer[8] += (inbuffer[8] * l[0]);
|
|
outbuffer[9] += (inbuffer[9] * l[1]);
|
|
outbuffer[10] += (inbuffer[10] * l[2]);
|
|
outbuffer[11] += (inbuffer[11] * l[3]);
|
|
outbuffer[12] += (inbuffer[12] * l[4]);
|
|
outbuffer[13] += (inbuffer[13] * l[5]);
|
|
outbuffer[14] += (inbuffer[14] * l[6]);
|
|
outbuffer[15] += (inbuffer[15] * l[7]);
|
|
|
|
outbuffer += 16;
|
|
inbuffer += 16;
|
|
len--;
|
|
}
|
|
|
|
len = length & 1;
|
|
if (len)
|
|
{
|
|
while (len)
|
|
{
|
|
outbuffer[0] += (inbuffer[0] * l[0]);
|
|
outbuffer[1] += (inbuffer[1] * l[1]);
|
|
outbuffer[2] += (inbuffer[2] * l[2]);
|
|
outbuffer[3] += (inbuffer[3] * l[3]);
|
|
outbuffer[4] += (inbuffer[4] * l[4]);
|
|
outbuffer[5] += (inbuffer[5] * l[5]);
|
|
outbuffer[6] += (inbuffer[6] * l[6]);
|
|
outbuffer[7] += (inbuffer[7] * l[7]);
|
|
|
|
inbuffer +=8;
|
|
outbuffer +=8;
|
|
len --;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (count = 0; count < length; count++)
|
|
{
|
|
int count2;
|
|
|
|
for (count2 = 0; count2 < outchannels; count2++)
|
|
{
|
|
float srcval = 0;
|
|
float destval = *outbuffer;
|
|
int count3;
|
|
|
|
for (count3 = 0; count3 < inchannels; count3++)
|
|
{
|
|
srcval += (inbuffer[count3] * levelcurrent[count2][count3]);
|
|
}
|
|
|
|
destval += srcval;
|
|
*outbuffer++ = destval;
|
|
}
|
|
inbuffer += inchannels;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
else
|
|
{
|
|
for (count = 0; count < length; count++)
|
|
{
|
|
int count2;
|
|
|
|
for (count2 = 0; count2 < outchannels; count2++)
|
|
{
|
|
float srcval = 0;
|
|
float destval = *outbuffer;
|
|
int count3;
|
|
|
|
for (count3 = 0; count3 < inchannels; count3++)
|
|
{
|
|
srcval += (inbuffer[count3] * levelcurrent[count2][count3]);
|
|
}
|
|
|
|
destval += srcval;
|
|
*outbuffer++ = destval;
|
|
}
|
|
inbuffer += inchannels;
|
|
}
|
|
}
|
|
|
|
return FMOD_OK;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
FMOD_OK
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT DSPConnectionI::mixAndRamp(float * FMOD_RESTRICT outbuffer, float * FMOD_RESTRICT inbuffer, int outchannels, int inchannels, unsigned int length)
|
|
{
|
|
unsigned int count;
|
|
#if (DSP_LEVEL_PRECISION == 16)
|
|
float levelcurrent[DSP_MAXLEVELS_OUT][DSP_MAXLEVELS_IN];
|
|
float leveldelta[DSP_MAXLEVELS_OUT][DSP_MAXLEVELS_IN];
|
|
|
|
for (count = 0; count < (unsigned int)outchannels; count++)
|
|
{
|
|
int count2;
|
|
|
|
for (count2 = 0; count2 < inchannels; count2++)
|
|
{
|
|
levelcurrent[count][count2] = DSP_LEVEL_DECOMPRESS(mLevelCurrent[count][count2]);
|
|
leveldelta[count][count2] = DSP_LEVEL_DECOMPRESS(mLevelDelta[count][count2]);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
for (count = 0; count < length; count++)
|
|
{
|
|
int count2;
|
|
|
|
for (count2 = 0; count2 < outchannels; count2++)
|
|
{
|
|
float srcval = 0;
|
|
float destval = *outbuffer;
|
|
int count3;
|
|
|
|
for (count3 = 0; count3 < inchannels; count3++)
|
|
{
|
|
#if (DSP_LEVEL_PRECISION == 32)
|
|
srcval += (inbuffer[count3] * mLevelCurrent[count2][count3]);
|
|
mLevelCurrent[count2][count3] += mLevelDelta[count2][count3];
|
|
#else
|
|
srcval += (inbuffer[count3] * levelcurrent[count2][count3]);
|
|
levelcurrent[count2][count3] += leveldelta[count2][count3];
|
|
#endif
|
|
}
|
|
|
|
destval += srcval;
|
|
*outbuffer++ = destval;
|
|
}
|
|
|
|
inbuffer += inchannels;
|
|
}
|
|
|
|
#if (DSP_LEVEL_PRECISION == 16)
|
|
for (count = 0; count < (unsigned int)outchannels; count++)
|
|
{
|
|
int count2;
|
|
|
|
for (count2 = 0; count2 < inchannels; count2++)
|
|
{
|
|
mLevelCurrent[count][count2] = DSP_LEVEL_COMPRESS(levelcurrent[count][count2]);
|
|
mLevelDelta[count][count2] = DSP_LEVEL_COMPRESS(leveldelta[count][count2]);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
mRampCount -= length;
|
|
|
|
/*
|
|
Snap the current to the mlevel
|
|
*/
|
|
if (!mRampCount)
|
|
{
|
|
int count, count2;
|
|
|
|
for (count = 0; count < mMaxOutputLevels; count++)
|
|
{
|
|
for (count2 = 0; count2 < mMaxInputLevels; count2++)
|
|
{
|
|
mLevelCurrent[count][count2] = DSP_LEVEL_COMPRESS(DSP_LEVEL_DECOMPRESS(mLevel[count][count2]) * mVolume);
|
|
}
|
|
}
|
|
}
|
|
|
|
return FMOD_OK;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
FMOD_OK
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT DSPConnectionI::rampTo()
|
|
{
|
|
int count;
|
|
float oorampcount, delta = 0;
|
|
|
|
oorampcount = 1.0f / DSP_RAMPCOUNT;
|
|
|
|
if (mMaxInputLevels == 6)
|
|
{
|
|
for (count = 0; count < mMaxOutputLevels; count++)
|
|
{
|
|
float value;
|
|
|
|
value = ((DSP_LEVEL_DECOMPRESS(mLevel[count][0]) * mVolume) - DSP_LEVEL_DECOMPRESS(mLevelCurrent[count][0])) * oorampcount;
|
|
delta += FMOD_FABS(value);
|
|
mLevelDelta[count][0] = DSP_LEVEL_COMPRESS(value);
|
|
value = ((DSP_LEVEL_DECOMPRESS(mLevel[count][1]) * mVolume) - DSP_LEVEL_DECOMPRESS(mLevelCurrent[count][1])) * oorampcount;
|
|
delta += FMOD_FABS(value);
|
|
mLevelDelta[count][1] = DSP_LEVEL_COMPRESS(value);
|
|
value = ((DSP_LEVEL_DECOMPRESS(mLevel[count][2]) * mVolume) - DSP_LEVEL_DECOMPRESS(mLevelCurrent[count][2])) * oorampcount;
|
|
delta += FMOD_FABS(value);
|
|
mLevelDelta[count][2] = DSP_LEVEL_COMPRESS(value);
|
|
value = ((DSP_LEVEL_DECOMPRESS(mLevel[count][3]) * mVolume) - DSP_LEVEL_DECOMPRESS(mLevelCurrent[count][3])) * oorampcount;
|
|
delta += FMOD_FABS(value);
|
|
mLevelDelta[count][3] = DSP_LEVEL_COMPRESS(value);
|
|
value = ((DSP_LEVEL_DECOMPRESS(mLevel[count][4]) * mVolume) - DSP_LEVEL_DECOMPRESS(mLevelCurrent[count][4])) * oorampcount;
|
|
delta += FMOD_FABS(value);
|
|
mLevelDelta[count][4] = DSP_LEVEL_COMPRESS(value);
|
|
value = ((DSP_LEVEL_DECOMPRESS(mLevel[count][5]) * mVolume) - DSP_LEVEL_DECOMPRESS(mLevelCurrent[count][5])) * oorampcount;
|
|
delta += FMOD_FABS(value);
|
|
mLevelDelta[count][5] = DSP_LEVEL_COMPRESS(value);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int count2;
|
|
|
|
for (count = 0; count < mMaxOutputLevels; count++)
|
|
{
|
|
for (count2 = 0; count2 < mMaxInputLevels; count2++)
|
|
{
|
|
float value;
|
|
|
|
value = ((DSP_LEVEL_DECOMPRESS(mLevel[count][count2]) *mVolume) - DSP_LEVEL_DECOMPRESS(mLevelCurrent[count][count2])) * oorampcount;
|
|
delta += FMOD_FABS(value);
|
|
mLevelDelta[count][count2] = DSP_LEVEL_COMPRESS(value);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (DSP_LEVEL_COMPRESS(delta) >= 0.000001f)
|
|
{
|
|
mRampCount = DSP_RAMPCOUNT; /* Only trigger the ramp if anything has changed. */
|
|
}
|
|
|
|
return FMOD_OK;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
FMOD_OK
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT DSPConnectionI::checkUnity(int outchannels, int inchannels)
|
|
{
|
|
int count, count2;
|
|
|
|
if (inchannels != outchannels)
|
|
{
|
|
return FMOD_ERR_INVALID_PARAM;
|
|
}
|
|
|
|
if (mRampCount != 0)
|
|
{
|
|
return FMOD_ERR_PAN;
|
|
}
|
|
|
|
if (mVolume != 1.0f)
|
|
{
|
|
return FMOD_ERR_PAN;
|
|
}
|
|
|
|
for (count = 0; count < outchannels; count++)
|
|
{
|
|
for (count2 = 0; count2 < inchannels; count2++)
|
|
{
|
|
if (count == count2 && DSP_LEVEL_DECOMPRESS(mLevel[count][count2]) != 1.0f)
|
|
{
|
|
return FMOD_ERR_PAN;
|
|
}
|
|
else if (count != count2 && mLevel[count][count2] != 0)
|
|
{
|
|
return FMOD_ERR_PAN;
|
|
}
|
|
}
|
|
}
|
|
|
|
return FMOD_OK;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
FMOD_OK
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT DSPConnectionI::checkMono(int outchannels, int inchannels)
|
|
{
|
|
int count, count2;
|
|
|
|
if (inchannels == 1)
|
|
{
|
|
return FMOD_OK;
|
|
}
|
|
|
|
for (count = 0; count < outchannels; count++)
|
|
{
|
|
for (count2 = 1; count2 < inchannels; count2++)
|
|
{
|
|
if (mLevel[count][count2] != 0)
|
|
{
|
|
return FMOD_ERR_TOOMANYCHANNELS;
|
|
}
|
|
}
|
|
}
|
|
|
|
return FMOD_OK;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
FMOD_OK
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT DSPConnectionI::setPan(float pan, int outchannels, int inchannels, FMOD_SPEAKERMODE speakermode)
|
|
{
|
|
int count, count2;
|
|
|
|
#ifndef PLATFORM_PS3_SPU
|
|
if (!mInputUnit->mSystem)
|
|
{
|
|
return FMOD_ERR_INTERNAL;
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
First clear out all levels to 0.
|
|
*/
|
|
for (count = 0; count < outchannels; count++)
|
|
{
|
|
for (count2 = 0; count2 < inchannels; count2++)
|
|
{
|
|
mLevel[count][count2] = 0;
|
|
}
|
|
}
|
|
|
|
switch (speakermode)
|
|
{
|
|
#ifdef FMOD_SUPPORT_SPEAKERMODE_RAW
|
|
case FMOD_SPEAKERMODE_RAW:
|
|
{
|
|
/*
|
|
Map 1 input channel to each output channel sequentially. For example.
|
|
|
|
1 0 0 0 0 0 0 0 or 1 0 0 0 or 1 0 or 1 or 1 0 0 0 0 0 0 0 or 1 0 0 0 or 1 0 or 1
|
|
0 1 0 0 0 0 0 0 0 1 0 0 0 1 0 0 1 0 0 0 0 0 0 0 1 0 0 0 1 0
|
|
0 0 1 0 0 0 0 0 0 0 1 0 0 0 0
|
|
0 0 0 1 0 0 0 0 0 0 0 1 0 0 0
|
|
0 0 0 0 1 0 0 0 0 0 0 0 0 0 0
|
|
0 0 0 0 0 1 0 0 0 0 0 0 0 0 0
|
|
0 0 0 0 0 0 1 0 0 0 0 0 0 0 0
|
|
0 0 0 0 0 0 0 1 0 0 0 0 0 0 0
|
|
*/
|
|
for (count = 0; count < outchannels; count++)
|
|
{
|
|
for (count2 = 0; count2 < inchannels; count2++)
|
|
{
|
|
if (count == count2)
|
|
{
|
|
mLevel[count][count2] = DSP_LEVEL_COMPRESS(1.0f);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
#endif
|
|
#ifdef FMOD_SUPPORT_SPEAKERMODE_MONO
|
|
case FMOD_SPEAKERMODE_MONO:
|
|
{
|
|
for (count = 0; count < inchannels; count++)
|
|
{
|
|
mLevel[0][count] = DSP_LEVEL_COMPRESS(1.0f);
|
|
}
|
|
break;
|
|
}
|
|
#endif
|
|
#ifdef FMOD_SUPPORT_SPEAKERMODE_STEREO
|
|
case FMOD_SPEAKERMODE_STEREO:
|
|
case FMOD_SPEAKERMODE_STEREO_LINEAR:
|
|
{
|
|
float l,r;
|
|
|
|
pan = (pan + 1.0f) / 2.0f;
|
|
|
|
if (inchannels == 1)
|
|
{
|
|
l = 1.0f - pan;
|
|
r = pan;
|
|
|
|
if (speakermode == FMOD_SPEAKERMODE_STEREO)
|
|
{
|
|
l = FMOD_SQRT(l);
|
|
r = FMOD_SQRT(r);
|
|
}
|
|
|
|
mLevel[0][0] = DSP_LEVEL_COMPRESS(l);
|
|
mLevel[1][0] = DSP_LEVEL_COMPRESS(r);
|
|
}
|
|
else if (inchannels == 2 || inchannels == 4 || inchannels == 6 || inchannels == 8)
|
|
{
|
|
/*
|
|
Stereo source panning is 0 = 1.0:0.0. 0.5 = 1.0:1.0. 1.0 = 0:1.0.
|
|
*/
|
|
if (pan <= 0.5f)
|
|
{
|
|
l = 1.0f;
|
|
r = pan * 2.0f;
|
|
}
|
|
else
|
|
{
|
|
l = (1.0f - pan) * 2.0f;
|
|
r = 1.0f;
|
|
}
|
|
|
|
if (inchannels == 2)
|
|
{
|
|
mLevel[0][0] = DSP_LEVEL_COMPRESS(l);
|
|
mLevel[1][1] = DSP_LEVEL_COMPRESS(r);
|
|
}
|
|
else if (inchannels == 4)
|
|
{
|
|
/*
|
|
Prologic downmix. Assuming LCRS
|
|
*/
|
|
mLevel[0][0] = DSP_LEVEL_COMPRESS( 1.0f * l);
|
|
mLevel[0][1] = DSP_LEVEL_COMPRESS( 0.0f * l);
|
|
mLevel[0][2] = DSP_LEVEL_COMPRESS( 0.707f * l);
|
|
mLevel[0][3] = DSP_LEVEL_COMPRESS( -0.707f * l); /* Discard LFE */
|
|
|
|
mLevel[1][0] = DSP_LEVEL_COMPRESS( 0.0f * r);
|
|
mLevel[1][1] = DSP_LEVEL_COMPRESS( 1.0f * r);
|
|
mLevel[1][2] = DSP_LEVEL_COMPRESS( 0.707f * r);
|
|
mLevel[1][3] = DSP_LEVEL_COMPRESS( -0.707f * r); /* Discard LFE */
|
|
}
|
|
else if (inchannels == 6)
|
|
{
|
|
/*
|
|
Prologic 2 downmix.
|
|
*/
|
|
mLevel[0][0] = DSP_LEVEL_COMPRESS( 1.0f * l);
|
|
mLevel[0][1] = DSP_LEVEL_COMPRESS( 0.0f * l);
|
|
mLevel[0][2] = DSP_LEVEL_COMPRESS( 0.707f * l);
|
|
mLevel[0][3] = DSP_LEVEL_COMPRESS( 0.0f * l); /* Discard LFE */
|
|
mLevel[0][4] = DSP_LEVEL_COMPRESS(-0.872f * l);
|
|
mLevel[0][5] = DSP_LEVEL_COMPRESS(-0.49f * l);
|
|
|
|
mLevel[1][0] = DSP_LEVEL_COMPRESS( 0.0f * r);
|
|
mLevel[1][1] = DSP_LEVEL_COMPRESS( 1.0f * r);
|
|
mLevel[1][2] = DSP_LEVEL_COMPRESS( 0.707f * r);
|
|
mLevel[1][3] = DSP_LEVEL_COMPRESS( 0.0f * r); /* Discard LFE */
|
|
mLevel[1][4] = DSP_LEVEL_COMPRESS( 0.49f * r);
|
|
mLevel[1][5] = DSP_LEVEL_COMPRESS( 0.872f * r);
|
|
}
|
|
else if (inchannels == 8)
|
|
{
|
|
/*
|
|
Prologic 2x downmix?
|
|
*/
|
|
mLevel[0][0] = DSP_LEVEL_COMPRESS( 1.0f * l);
|
|
mLevel[0][1] = DSP_LEVEL_COMPRESS( 0.0f * l);
|
|
mLevel[0][2] = DSP_LEVEL_COMPRESS( 0.707f * l);
|
|
mLevel[0][3] = DSP_LEVEL_COMPRESS( 0.0f * l); /* Discard LFE */
|
|
mLevel[0][4] = DSP_LEVEL_COMPRESS(-0.872f * l);
|
|
mLevel[0][5] = DSP_LEVEL_COMPRESS(-0.49f * l);
|
|
|
|
mLevel[0][6] = DSP_LEVEL_COMPRESS( 1.0f * l); /* Not sure here. Need PLIIx coefficients for 7.1? */
|
|
mLevel[0][7] = DSP_LEVEL_COMPRESS( 0.0f * l); /* Not sure here. Need PLIIx coefficients for 7.1? */
|
|
|
|
mLevel[1][0] = DSP_LEVEL_COMPRESS( 0.0f * r);
|
|
mLevel[1][1] = DSP_LEVEL_COMPRESS( 1.0f * r);
|
|
mLevel[1][2] = DSP_LEVEL_COMPRESS( 0.707f * r);
|
|
mLevel[1][3] = DSP_LEVEL_COMPRESS( 0.0f * r); /* Discard LFE */
|
|
mLevel[1][4] = DSP_LEVEL_COMPRESS( 0.49f * r);
|
|
mLevel[1][5] = DSP_LEVEL_COMPRESS( 0.872f * r);
|
|
|
|
mLevel[1][6] = DSP_LEVEL_COMPRESS( 0.0f * r); /* Not sure here. Need PLIIx coefficients for 7.1? */
|
|
mLevel[1][7] = DSP_LEVEL_COMPRESS( 1.0f * r); /* Not sure here. Need PLIIx coefficients for 7.1? */
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
Map 1 input channel to each output channel sequentially. For example.
|
|
|
|
1 0 0 0 0 0 0 0 or 1 0 0 0 or 1 0 or 1 or 1 0 0 0 0 0 0 0 or 1 0 0 0 or 1 0 or 1
|
|
0 1 0 0 0 0 0 0 0 1 0 0 0 1 0 0 1 0 0 0 0 0 0 0 1 0 0 0 1 0
|
|
0 0 1 0 0 0 0 0 0 0 1 0 0 0 0
|
|
0 0 0 1 0 0 0 0 0 0 0 1 0 0 0
|
|
0 0 0 0 1 0 0 0 0 0 0 0 0 0 0
|
|
0 0 0 0 0 1 0 0 0 0 0 0 0 0 0
|
|
0 0 0 0 0 0 1 0 0 0 0 0 0 0 0
|
|
0 0 0 0 0 0 0 1 0 0 0 0 0 0 0
|
|
*/
|
|
for (count = 0; count < outchannels; count++)
|
|
{
|
|
for (count2 = 0; count2 < inchannels; count2++)
|
|
{
|
|
if (count == count2)
|
|
{
|
|
mLevel[count][count2] = DSP_LEVEL_COMPRESS(1.0f);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
#endif
|
|
case FMOD_SPEAKERMODE_QUAD:
|
|
case FMOD_SPEAKERMODE_SURROUND:
|
|
case FMOD_SPEAKERMODE_5POINT1:
|
|
case FMOD_SPEAKERMODE_7POINT1:
|
|
{
|
|
float l,r;
|
|
|
|
pan = (pan + 1.0f) / 2.0f;
|
|
|
|
if (inchannels == 1)
|
|
{
|
|
l = 1.0f - pan;
|
|
r = pan;
|
|
|
|
l = FMOD_SQRT(l);
|
|
r = FMOD_SQRT(r);
|
|
|
|
mLevel[0][0] = DSP_LEVEL_COMPRESS(l);
|
|
mLevel[1][0] = DSP_LEVEL_COMPRESS(r);
|
|
}
|
|
else if (inchannels == 2)
|
|
{
|
|
/*
|
|
Stereo source panning is 0.0 = 1.0:0.0. 0.5 = 1.0:1.0. 1.0 = 0.0:1.0.
|
|
*/
|
|
if (pan <= 0.5f)
|
|
{
|
|
l = 1.0f;
|
|
r = pan * 2.0f;
|
|
}
|
|
else
|
|
{
|
|
l = (1.0f - pan) * 2.0f;
|
|
r = 1.0f;
|
|
}
|
|
|
|
mLevel[0][0] = DSP_LEVEL_COMPRESS(l);
|
|
mLevel[1][1] = DSP_LEVEL_COMPRESS(r);
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
Map 1 input channel to each output channel sequentially. For example.
|
|
|
|
1 0 0 0 0 0 0 0 or 1 0 0 0 or 1 0 or 1 or 1 0 0 0 0 0 0 0 or 1 0 0 0 or 1 0 or 1
|
|
0 1 0 0 0 0 0 0 0 1 0 0 0 1 0 0 1 0 0 0 0 0 0 0 1 0 0 0 1 0
|
|
0 0 1 0 0 0 0 0 0 0 1 0 0 0 0
|
|
0 0 0 1 0 0 0 0 0 0 0 1 0 0 0
|
|
0 0 0 0 1 0 0 0 0 0 0 0 0 0 0
|
|
0 0 0 0 0 1 0 0 0 0 0 0 0 0 0
|
|
0 0 0 0 0 0 1 0 0 0 0 0 0 0 0
|
|
0 0 0 0 0 0 0 1 0 0 0 0 0 0 0
|
|
*/
|
|
for (count = 0; count < outchannels; count++)
|
|
{
|
|
for (count2 = 0; count2 < inchannels; count2++)
|
|
{
|
|
if (count == count2)
|
|
{
|
|
mLevel[count][count2] = DSP_LEVEL_COMPRESS(1.0f);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
#ifdef FMOD_SUPPORT_SPEAKERMODE_PROLOGIC
|
|
case FMOD_SPEAKERMODE_PROLOGIC:
|
|
{
|
|
float l,r;
|
|
|
|
pan = (pan + 1.0f) / 2.0f;
|
|
|
|
if (inchannels == 1)
|
|
{
|
|
l = 1.0f - pan;
|
|
r = pan;
|
|
|
|
l = FMOD_SQRT(l);
|
|
r = FMOD_SQRT(r);
|
|
|
|
mLevel[0][0] = DSP_LEVEL_COMPRESS(l);
|
|
mLevel[1][0] = DSP_LEVEL_COMPRESS(r);
|
|
}
|
|
else if (inchannels == 2)
|
|
{
|
|
/*
|
|
Stereo source panning is 0.0 = 1.0:0.0. 0.5 = 1.0:1.0. 1.0 = 0:1.0.
|
|
*/
|
|
if (pan < 0.5f)
|
|
{
|
|
l = 1.0f;
|
|
r = pan * 2.0f;
|
|
}
|
|
else
|
|
{
|
|
l = (1.0f - pan) * 2.0f;
|
|
r = 1.0f;
|
|
}
|
|
|
|
mLevel[0][0] = DSP_LEVEL_COMPRESS(l);
|
|
mLevel[1][1] = DSP_LEVEL_COMPRESS(r);
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
Map 1 input channel to each output channel sequentially. For example.
|
|
|
|
1 0 0 0 0 0 0 0 or 1 0 0 0 or 1 0 or 1 or 1 0 0 0 0 0 0 0 or 1 0 0 0 or 1 0 or 1
|
|
0 1 0 0 0 0 0 0 0 1 0 0 0 1 0 0 1 0 0 0 0 0 0 0 1 0 0 0 1 0
|
|
0 0 1 0 0 0 0 0 0 0 1 0 0 0 0
|
|
0 0 0 1 0 0 0 0 0 0 0 1 0 0 0
|
|
0 0 0 0 1 0 0 0 0 0 0 0 0 0 0
|
|
0 0 0 0 0 1 0 0 0 0 0 0 0 0 0
|
|
0 0 0 0 0 0 1 0 0 0 0 0 0 0 0
|
|
0 0 0 0 0 0 0 1 0 0 0 0 0 0 0
|
|
*/
|
|
for (count = 0; count < outchannels; count++)
|
|
{
|
|
for (count2 = 0; count2 < inchannels; count2++)
|
|
{
|
|
if (count == count2)
|
|
{
|
|
mLevel[count][count2] = DSP_LEVEL_COMPRESS(1.0f);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
#endif
|
|
default:
|
|
{
|
|
break;
|
|
}
|
|
};
|
|
|
|
mSetLevelsUsed = true;
|
|
|
|
return rampTo();
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
1 [RETURN_VALUE]
|
|
FMOD_OK
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT DSPConnectionI::setLevels(float *levels, int numinputlevels)
|
|
{
|
|
int count, count2;
|
|
|
|
if (!levels)
|
|
{
|
|
return FMOD_ERR_INVALID_PARAM;
|
|
}
|
|
|
|
if (!numinputlevels)
|
|
{
|
|
return FMOD_OK;
|
|
}
|
|
|
|
#if (DSP_MAXLEVELS_OUT > 2)
|
|
if (mMaxOutputLevels == 6 && numinputlevels < 3)
|
|
{
|
|
if (numinputlevels == 1)
|
|
{
|
|
mLevel[0][0] = DSP_LEVEL_COMPRESS(levels[0]);
|
|
mLevel[1][0] = DSP_LEVEL_COMPRESS(levels[1]);
|
|
mLevel[2][0] = DSP_LEVEL_COMPRESS(levels[2]);
|
|
mLevel[3][0] = DSP_LEVEL_COMPRESS(levels[3]);
|
|
mLevel[4][0] = DSP_LEVEL_COMPRESS(levels[4]);
|
|
mLevel[5][0] = DSP_LEVEL_COMPRESS(levels[5]);
|
|
}
|
|
else
|
|
{
|
|
mLevel[0][0] = DSP_LEVEL_COMPRESS(levels[0]);
|
|
mLevel[0][1] = DSP_LEVEL_COMPRESS(levels[1]);
|
|
mLevel[1][0] = DSP_LEVEL_COMPRESS(levels[2]);
|
|
mLevel[1][1] = DSP_LEVEL_COMPRESS(levels[3]);
|
|
mLevel[2][0] = DSP_LEVEL_COMPRESS(levels[4]);
|
|
mLevel[2][1] = DSP_LEVEL_COMPRESS(levels[5]);
|
|
mLevel[3][0] = DSP_LEVEL_COMPRESS(levels[6]);
|
|
mLevel[3][1] = DSP_LEVEL_COMPRESS(levels[7]);
|
|
mLevel[4][0] = DSP_LEVEL_COMPRESS(levels[8]);
|
|
mLevel[4][1] = DSP_LEVEL_COMPRESS(levels[9]);
|
|
mLevel[5][0] = DSP_LEVEL_COMPRESS(levels[10]);
|
|
mLevel[5][1] = DSP_LEVEL_COMPRESS(levels[11]);
|
|
}
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
for (count = 0; count < mMaxOutputLevels; count++)
|
|
{
|
|
for (count2 = 0; count2 < mMaxInputLevels; count2++)
|
|
{
|
|
if (count2 < numinputlevels)
|
|
{
|
|
mLevel[count][count2] = DSP_LEVEL_COMPRESS(levels[(count * numinputlevels) + count2]);
|
|
}
|
|
else
|
|
{
|
|
mLevel[count][count2] = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
mSetLevelsUsed = true;
|
|
|
|
return rampTo();
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
FMOD_OK
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT DSPConnectionI::getLevels(float *levels, int numinputlevels)
|
|
{
|
|
int count, count2;
|
|
|
|
if (!levels)
|
|
{
|
|
return FMOD_ERR_INVALID_PARAM;
|
|
}
|
|
|
|
for (count = 0; count < mMaxOutputLevels; count++)
|
|
{
|
|
for (count2 = 0; count2 < numinputlevels; count2++)
|
|
{
|
|
if (count2 < mMaxInputLevels)
|
|
{
|
|
levels[(count * numinputlevels) + count2] = DSP_LEVEL_DECOMPRESS(mLevel[count][count2]);
|
|
}
|
|
else
|
|
{
|
|
levels[(count * numinputlevels) + count2] = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
return FMOD_OK;
|
|
}
|
|
|
|
#endif /* #ifdef FMOD_SUPPORT_SOFTWARE */
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
FMOD_OK
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT DSPConnectionI::setMix(float volume)
|
|
{
|
|
#ifdef FMOD_SUPPORT_SOFTWARE
|
|
if (volume < -1.0f)
|
|
{
|
|
volume = -1.0f;
|
|
}
|
|
if (volume > 1.0f)
|
|
{
|
|
volume = 1.0f;
|
|
}
|
|
|
|
if (mVolume == volume)
|
|
{
|
|
return FMOD_OK;
|
|
}
|
|
|
|
mVolume = volume;
|
|
|
|
return rampTo();
|
|
#else
|
|
return FMOD_ERR_NEEDSSOFTWARE;
|
|
#endif
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
FMOD_OK
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT DSPConnectionI::getMix(float *volume)
|
|
{
|
|
#ifdef FMOD_SUPPORT_SOFTWARE
|
|
if (!volume)
|
|
{
|
|
return FMOD_ERR_INVALID_PARAM;
|
|
}
|
|
|
|
*volume = mVolume;
|
|
|
|
return FMOD_OK;
|
|
#else
|
|
return FMOD_ERR_NEEDSSOFTWARE;
|
|
#endif
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
FMOD_OK
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT DSPConnectionI::setLevels(FMOD_SPEAKER speaker, float *levels, int numinputlevels)
|
|
{
|
|
#ifdef FMOD_SUPPORT_SOFTWARE
|
|
int count;
|
|
|
|
if (!levels)
|
|
{
|
|
return FMOD_ERR_INVALID_PARAM;
|
|
}
|
|
|
|
if (!numinputlevels)
|
|
{
|
|
return FMOD_OK;
|
|
}
|
|
|
|
if (speaker >= mMaxOutputLevels)
|
|
{
|
|
return FMOD_ERR_INVALID_SPEAKER;
|
|
}
|
|
|
|
for (count = 0; count < mMaxInputLevels; count++)
|
|
{
|
|
if (count < numinputlevels)
|
|
{
|
|
mLevel[speaker][count] = DSP_LEVEL_COMPRESS(levels[count]);
|
|
}
|
|
else
|
|
{
|
|
mLevel[speaker][count] = 0;
|
|
}
|
|
}
|
|
|
|
mSetLevelsUsed = true;
|
|
|
|
return rampTo();
|
|
#else
|
|
return FMOD_ERR_NEEDSSOFTWARE;
|
|
#endif
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
FMOD_OK
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT DSPConnectionI::getLevels(FMOD_SPEAKER speaker, float *levels, int numinputlevels)
|
|
{
|
|
#ifdef FMOD_SUPPORT_SOFTWARE
|
|
int count;
|
|
|
|
if (!levels)
|
|
{
|
|
return FMOD_ERR_INVALID_PARAM;
|
|
}
|
|
|
|
for (count = 0; count < numinputlevels; count++)
|
|
{
|
|
if (count < mMaxInputLevels)
|
|
{
|
|
levels[count] = DSP_LEVEL_DECOMPRESS(mLevel[speaker][count]);
|
|
}
|
|
else
|
|
{
|
|
levels[count] = 0;
|
|
}
|
|
}
|
|
|
|
return FMOD_OK;
|
|
#else
|
|
return FMOD_ERR_NEEDSSOFTWARE;
|
|
#endif
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT DSPConnectionI::setUserData(void *userdata)
|
|
{
|
|
mUserData = userdata;
|
|
|
|
return FMOD_OK;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT DSPConnectionI::getUserData(void **userdata)
|
|
{
|
|
if (!userdata)
|
|
{
|
|
return FMOD_ERR_INVALID_PARAM;
|
|
}
|
|
|
|
*userdata = mUserData;
|
|
|
|
return FMOD_OK;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
FMOD_OK
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
#ifdef FMOD_SUPPORT_SOFTWARE
|
|
FMOD_RESULT DSPConnectionI::copy(DSPConnectionI *source)
|
|
{
|
|
int count, count2;
|
|
|
|
mVolume = source->mVolume;
|
|
|
|
for (count = 0; count < mMaxOutputLevels; count++)
|
|
{
|
|
for (count2 = 0; count2 < mMaxInputLevels; count2++)
|
|
{
|
|
mLevel [count][count2] = source->mLevel [count][count2];
|
|
mLevelCurrent[count][count2] = source->mLevelCurrent[count][count2];
|
|
mLevelDelta [count][count2] = source->mLevelDelta [count][count2];
|
|
}
|
|
}
|
|
|
|
mRampCount = source->mRampCount;
|
|
mSetLevelsUsed = source->mSetLevelsUsed;
|
|
|
|
return FMOD_OK;
|
|
}
|
|
#endif
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT DSPConnectionI::getMemoryInfo(unsigned int memorybits, unsigned int event_memorybits, unsigned int *memoryused, FMOD_MEMORY_USAGE_DETAILS *memoryused_details)
|
|
{
|
|
#ifdef FMOD_SUPPORT_MEMORYTRACKER
|
|
GETMEMORYINFO_IMPL
|
|
#else
|
|
return FMOD_ERR_UNIMPLEMENTED;
|
|
#endif
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
|
|
#if defined(FMOD_SUPPORT_MEMORYTRACKER) && !defined(PLATFORM_PS3_SPU)
|
|
|
|
FMOD_RESULT DSPConnectionI::getMemoryUsedImpl(MemoryTracker *tracker)
|
|
{
|
|
tracker->add(false, FMOD_MEMBITS_DSPCONNECTION, sizeof(*this));
|
|
|
|
// LinkedListNode mInputNode;
|
|
// LinkedListNode mOutputNode;
|
|
// LinkedListNode *mNode; /* Make it a pointer so we can store the node data externally. PS3 will corrupt it otherwise. */
|
|
|
|
// DSP_LEVEL_TYPE *mLevel[DSP_MAXLEVELS_OUT];
|
|
// DSP_LEVEL_TYPE *mLevelCurrent[DSP_MAXLEVELS_OUT];
|
|
// DSP_LEVEL_TYPE *mLevelDelta[DSP_MAXLEVELS_OUT];
|
|
|
|
// DSPI *mInputUnit;
|
|
// DSPI *mOutputUnit;
|
|
|
|
return FMOD_OK;
|
|
}
|
|
|
|
#endif
|
|
|
|
#if (DSP_LEVEL_PRECISION == 16) && !defined(PLATFORM_XENON)
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
unsigned short FMOD_DSP_ConnectionI_Single2HalfP(float source)
|
|
{
|
|
typedef union
|
|
{
|
|
float f;
|
|
unsigned int i;
|
|
} floatdata;
|
|
|
|
floatdata x;
|
|
unsigned short hs, he, hm;
|
|
unsigned int xs, xe, xm;
|
|
int hes;
|
|
|
|
x.f = source;
|
|
|
|
if( (x.i & 0x7FFFFFFFu) == 0 )
|
|
{ // Signed zero
|
|
return (unsigned short) (x.i >> 16); // Return the signed zero
|
|
}
|
|
else
|
|
{ // Not zero
|
|
xs = x.i & 0x80000000u; // Pick off sign bit
|
|
xe = x.i & 0x7F800000u; // Pick off exponent bits
|
|
xm = x.i & 0x007FFFFFu; // Pick off mantissa bits
|
|
if( xe == 0 )
|
|
{ // Denormal will underflow, return a signed zero
|
|
return (unsigned short) (xs >> 16);
|
|
} else if( xe == 0x7F800000u )
|
|
{ // Inf or NaN (all the exponent bits are set)
|
|
if( xm == 0 )
|
|
{ // If mantissa is zero ...
|
|
return (unsigned short) ((xs >> 16) | 0x7C00u); // Signed Inf
|
|
} else
|
|
{
|
|
return (unsigned short) 0xFE00u; // NaN, only 1st mantissa bit set
|
|
}
|
|
} else
|
|
{ // Normalized number
|
|
hs = (unsigned short) (xs >> 16); // Sign bit
|
|
hes = ((int)(xe >> 23)) - 127 + 15; // Exponent unbias the single, then bias the halfp
|
|
if( hes >= 0x1F )
|
|
{ // Overflow
|
|
return (unsigned short) ((xs >> 16) | 0x7C00u); // Signed Inf
|
|
} else if( hes <= 0 )
|
|
{ // Underflow
|
|
if( (14 - hes) > 24 )
|
|
{ // Mantissa shifted all the way off & no rounding possibility
|
|
hm = (unsigned short) 0u; // Set mantissa to zero
|
|
}
|
|
else
|
|
{
|
|
xm |= 0x00800000u; // Add the hidden leading bit
|
|
hm = (unsigned short) (xm >> (14 - hes)); // Mantissa
|
|
if( (xm >> (13 - hes)) & 0x00000001u ) // Check for rounding
|
|
hm += (unsigned short) 1u; // Round, might overflow into exp bit, but this is OK
|
|
}
|
|
return (hs | hm); // Combine sign bit and mantissa bits, biased exponent is zero
|
|
} else
|
|
{
|
|
he = (unsigned short) (hes << 10); // Exponent
|
|
hm = (unsigned short) (xm >> 13); // Mantissa
|
|
if( xm & 0x00001000u ) // Check for rounding
|
|
return (hs | he | hm) + (unsigned short) 1u; // Round, might overflow to inf, this is OK
|
|
else
|
|
return (hs | he | hm); // No rounding
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
float FMOD_DSP_ConnectionI_HalfP2Single(unsigned short h)
|
|
{
|
|
typedef union
|
|
{
|
|
float f;
|
|
unsigned int i;
|
|
} floatdata;
|
|
|
|
unsigned short hs, he, hm;
|
|
unsigned int xs, xe, xm;
|
|
signed int xes;
|
|
floatdata xp;
|
|
int e;
|
|
|
|
if( (h & 0x7FFFu) == 0 )
|
|
{ // Signed zero
|
|
xp.i = ((unsigned int) h) << 16; // Return the signed zero
|
|
}
|
|
else
|
|
{ // Not zero
|
|
hs = h & 0x8000u; // Pick off sign bit
|
|
he = h & 0x7C00u; // Pick off exponent bits
|
|
hm = h & 0x03FFu; // Pick off mantissa bits
|
|
if( he == 0 )
|
|
{ // Denormal will convert to normalized
|
|
e = -1; // The following loop figures out how much extra to adjust the exponent
|
|
do
|
|
{
|
|
e++;
|
|
hm <<= 1;
|
|
} while( (hm & 0x0400u) == 0 ); // Shift until leading bit overflows into exponent bit
|
|
xs = ((unsigned int) hs) << 16; // Sign bit
|
|
xes = ((signed int) (he >> 10)) - 15 + 127 - e; // Exponent unbias the halfp, then bias the single
|
|
xe = (unsigned int) (xes << 23); // Exponent
|
|
xm = ((unsigned int) (hm & 0x03FFu)) << 13; // Mantissa
|
|
xp.i = (xs | xe | xm); // Combine sign bit, exponent bits, and mantissa bits
|
|
}
|
|
else if( he == 0x7C00u )
|
|
{ // Inf or NaN (all the exponent bits are set)
|
|
if( hm == 0 )
|
|
{ // If mantissa is zero ...
|
|
xp.i = (((unsigned int) hs) << 16) | ((unsigned int) 0x7F800000u); // Signed Inf
|
|
} else
|
|
{
|
|
xp.i = (unsigned int) 0xFFC00000u; // NaN, only 1st mantissa bit set
|
|
}
|
|
}
|
|
else
|
|
{ // Normalized number
|
|
xs = ((unsigned int) hs) << 16; // Sign bit
|
|
xes = ((signed int) (he >> 10)) - 15 + 127; // Exponent unbias the halfp, then bias the single
|
|
xe = (unsigned int) (xes << 23); // Exponent
|
|
xm = ((unsigned int) hm) << 13; // Mantissa
|
|
xp.i = (xs | xe | xm); // Combine sign bit, exponent bits, and mantissa bits
|
|
}
|
|
}
|
|
return xp.f;
|
|
}
|
|
#endif
|
|
|
|
}
|