381 lines
10 KiB
C++
Executable file
381 lines
10 KiB
C++
Executable file
#include "fmod_settings.h"
|
|
|
|
#ifdef FMOD_SUPPORT_SOFTWARE
|
|
|
|
#include "fmod_dsp_connectionpool.h"
|
|
#include "fmod_localcriticalsection.h"
|
|
#include "fmod_memory.h"
|
|
#include "fmod_systemi.h"
|
|
|
|
namespace FMOD
|
|
{
|
|
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT DSPConnectionPool::init(SystemI *system, int numconnections, int numoutputlevels, int numinputlevels)
|
|
{
|
|
DSP_LEVEL_TYPE *leveldata;
|
|
int count;
|
|
unsigned int alignment = 0;
|
|
|
|
if (numconnections < 0)
|
|
{
|
|
return FMOD_ERR_INVALID_PARAM;
|
|
}
|
|
|
|
for (int i=0; i < DSP_MAX_CONNECTION_BLOCKS; i++)
|
|
{
|
|
mConnection[i] = 0;
|
|
mLevelData[i] = 0;
|
|
}
|
|
|
|
numconnections += 128;
|
|
numconnections /= 128;
|
|
numconnections *= 128;
|
|
|
|
mNumConnections = numconnections;
|
|
mConnectionMemory[0] = (DSPConnectionI *)FMOD_Memory_Calloc(mNumConnections * sizeof(DSPConnectionI) + 16);
|
|
if (!mConnectionMemory[0])
|
|
{
|
|
return FMOD_ERR_MEMORY;
|
|
}
|
|
mConnection[0] = (DSPConnectionI *)FMOD_ALIGNPOINTER(mConnectionMemory[0], 16);
|
|
|
|
mNodeMemory[0] = (LinkedListNode *)FMOD_Memory_Calloc(mNumConnections * sizeof(LinkedListNode));
|
|
if (!mNodeMemory[0])
|
|
{
|
|
return FMOD_ERR_MEMORY;
|
|
}
|
|
|
|
mNumOutputLevels = numoutputlevels;
|
|
mNumInputLevels = numinputlevels;
|
|
|
|
#ifdef PLATFORM_PS3
|
|
alignment = 128;
|
|
#endif
|
|
mLevelDataMemory[0] = (DSP_LEVEL_TYPE *)FMOD_Memory_Calloc(mNumConnections /* How many connections are we going to allow maximum. */
|
|
* (mNumOutputLevels < 2 ? 2 : mNumOutputLevels) /* Number of rows. This should be at least 2 for panning. */
|
|
* (mNumInputLevels < mNumOutputLevels ? mNumOutputLevels : mNumInputLevels) /* Because pan matricies can be [outputlevels][outputlevels] we need to have at least this */
|
|
* sizeof(DSP_LEVEL_TYPE) /* Float values of course. Maybe lower? */
|
|
* 3 /* *3 = mLevel, mLevelCurrent, mLevelDelta */
|
|
+ alignment /* PS3 - 128 byte aligned for DMA */
|
|
);
|
|
if (!mLevelDataMemory[0])
|
|
{
|
|
return FMOD_ERR_MEMORY;
|
|
}
|
|
#ifdef PLATFORM_PS3
|
|
mLevelData[0] = (DSP_LEVEL_TYPE *)FMOD_ALIGNPOINTER(mLevelDataMemory[0], 128);
|
|
#else
|
|
mLevelData[0] = mLevelDataMemory[0];
|
|
#endif
|
|
leveldata = mLevelData[0];
|
|
|
|
mFreeListHead.initNode();
|
|
for (count = 0; count < mNumConnections; count++)
|
|
{
|
|
DSPConnectionI *conn = &mConnection[0][count];
|
|
|
|
new (conn) DSPConnectionI;
|
|
|
|
conn->init(leveldata, numoutputlevels, numinputlevels);
|
|
conn->mNode = &mNodeMemory[0][count];
|
|
conn->mNode->setData(conn);
|
|
conn->mNode->addAfter(&mFreeListHead);
|
|
}
|
|
|
|
mSystem = system;
|
|
|
|
return FMOD_OK;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT DSPConnectionPool::close()
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < DSP_MAX_CONNECTION_BLOCKS; i++)
|
|
{
|
|
if (mConnectionMemory[i])
|
|
{
|
|
FMOD_Memory_Free(mConnectionMemory[i]);
|
|
mConnectionMemory[i] = 0;
|
|
}
|
|
mConnection[i] = 0;
|
|
|
|
if (mLevelDataMemory[i])
|
|
{
|
|
FMOD_Memory_Free(mLevelDataMemory[i]);
|
|
mLevelDataMemory[i] = 0;
|
|
}
|
|
mLevelData[i] = 0;
|
|
|
|
if (mNodeMemory[i])
|
|
{
|
|
FMOD_Memory_Free(mNodeMemory[i]);
|
|
mNodeMemory[i] = 0;
|
|
}
|
|
}
|
|
|
|
return FMOD_OK;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT DSPConnectionPool::alloc(DSPConnectionI **connection, bool protect)
|
|
{
|
|
LocalCriticalSection crit(mSystem->mDSPConnectionCrit);
|
|
DSPConnectionI *newconnection;
|
|
unsigned int alignment = 0;
|
|
|
|
if (!mSystem)
|
|
{
|
|
return FMOD_ERR_UNINITIALIZED;
|
|
}
|
|
|
|
if (!connection)
|
|
{
|
|
return FMOD_ERR_INVALID_PARAM;
|
|
}
|
|
|
|
if (protect)
|
|
{
|
|
crit.enter();
|
|
}
|
|
|
|
if (mFreeListHead.isEmpty())
|
|
{
|
|
int newblock, count;
|
|
DSP_LEVEL_TYPE *leveldata = 0;
|
|
|
|
for (newblock = 0; newblock < DSP_MAX_CONNECTION_BLOCKS; newblock++)
|
|
{
|
|
if (!mConnectionMemory[newblock])
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
if (newblock >= DSP_MAX_CONNECTION_BLOCKS)
|
|
{
|
|
FLOG((FMOD_DEBUG_LEVEL_LOG, __FILE__, __LINE__, "DSPConnectionPool::alloc", "DSP_MAX_CONNECTION_BLOCKS exceeded! Memory will leak!\n"));
|
|
return FMOD_ERR_INTERNAL;
|
|
}
|
|
|
|
mConnectionMemory[newblock] = (DSPConnectionI *)FMOD_Memory_Calloc(mNumConnections * sizeof(DSPConnectionI) + 16);
|
|
if (!mConnectionMemory[newblock])
|
|
{
|
|
return FMOD_ERR_MEMORY;
|
|
}
|
|
mConnection[newblock] = (DSPConnectionI *)FMOD_ALIGNPOINTER(mConnectionMemory[newblock], 16);
|
|
|
|
#ifdef PLATFORM_PS3
|
|
alignment = 128;
|
|
#endif
|
|
mNodeMemory[newblock] = (LinkedListNode *)FMOD_Memory_Calloc(mNumConnections * sizeof(LinkedListNode));
|
|
if (!mNodeMemory[newblock])
|
|
{
|
|
return FMOD_ERR_MEMORY;
|
|
}
|
|
|
|
mLevelDataMemory[newblock] = (DSP_LEVEL_TYPE *)FMOD_Memory_Calloc(mNumConnections /* How many connections are we going to allow maximum. */
|
|
* (mNumOutputLevels < 2 ? 2 : mNumOutputLevels) /* Number of rows. This should be at least 2 for panning. */
|
|
* (mNumInputLevels < mNumOutputLevels ? mNumOutputLevels : mNumInputLevels) /* Because pan matricies can be [outputlevels][outputlevels] we need to have at least this */
|
|
* sizeof(DSP_LEVEL_TYPE) /* Float values of course. Maybe lower? */
|
|
* 3 /* *3 = mLevel, mLevelCurrent, mLevelDelta */
|
|
+ alignment /* PS3 - 128 byte aligned for DMA */
|
|
);
|
|
if (!mLevelDataMemory[newblock])
|
|
{
|
|
return FMOD_ERR_MEMORY;
|
|
}
|
|
#ifdef PLATFORM_PS3
|
|
mLevelData[newblock] = (DSP_LEVEL_TYPE *)FMOD_ALIGNPOINTER(mLevelDataMemory[newblock], 128);
|
|
#else
|
|
mLevelData[newblock] = mLevelDataMemory[newblock];
|
|
#endif
|
|
|
|
leveldata = mLevelData[newblock];
|
|
|
|
for (count = 0; count < mNumConnections; count++)
|
|
{
|
|
DSPConnectionI *conn = &mConnection[newblock][count];
|
|
|
|
new (conn) DSPConnectionI;
|
|
|
|
conn->init(leveldata, mNumOutputLevels, mNumInputLevels);
|
|
conn->mNode = &mNodeMemory[newblock][count];
|
|
conn->mNode->setData(conn);
|
|
conn->mNode->addAfter(&mFreeListHead);
|
|
}
|
|
}
|
|
|
|
newconnection = (DSPConnectionI *)mFreeListHead.getNext()->getData();
|
|
|
|
newconnection->mInputNode.setData(newconnection);
|
|
newconnection->mOutputNode.setData(newconnection);
|
|
|
|
newconnection->mNode->removeNode();
|
|
newconnection->mNode->addAfter(&mUsedListHead);
|
|
|
|
if (protect)
|
|
{
|
|
crit.leave();
|
|
}
|
|
|
|
*connection = newconnection;
|
|
|
|
return FMOD_OK;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT DSPConnectionPool::free(DSPConnectionI *connection, bool protect)
|
|
{
|
|
LocalCriticalSection crit(mSystem->mDSPConnectionCrit);
|
|
|
|
if (!connection)
|
|
{
|
|
return FMOD_ERR_INVALID_PARAM;
|
|
}
|
|
|
|
if (protect)
|
|
{
|
|
crit.enter();
|
|
}
|
|
|
|
connection->mInputNode.removeNode();
|
|
connection->mOutputNode.removeNode();
|
|
|
|
connection->mInputUnit = 0;
|
|
connection->mOutputUnit = 0;
|
|
|
|
connection->mNode->removeNode();
|
|
connection->mNode->addAfter(&mFreeListHead);
|
|
connection->mNode->setData(connection);
|
|
|
|
if (protect)
|
|
{
|
|
crit.leave();
|
|
}
|
|
|
|
return FMOD_OK;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
|
|
#ifdef FMOD_SUPPORT_MEMORYTRACKER
|
|
|
|
FMOD_RESULT DSPConnectionPool::getMemoryUsedImpl(MemoryTracker *tracker)
|
|
{
|
|
for (int i=0; i < DSP_MAX_CONNECTION_BLOCKS; i++)
|
|
{
|
|
if (mConnectionMemory[i])
|
|
{
|
|
tracker->add(false, FMOD_MEMBITS_DSPCONNECTION, mNumConnections * sizeof(DSPConnectionI) + 16);
|
|
}
|
|
|
|
if (mNodeMemory[i])
|
|
{
|
|
tracker->add(false, FMOD_MEMBITS_DSPCONNECTION, mNumConnections * sizeof(LinkedListNode));
|
|
}
|
|
|
|
if (mLevelDataMemory[i])
|
|
{
|
|
unsigned int alignment = 0;
|
|
|
|
#ifdef PLATFORM_PS3
|
|
alignment = 128;
|
|
#endif
|
|
|
|
tracker->add(false, FMOD_MEMBITS_DSPCONNECTION, mNumConnections /* How many connections are we going to allow maximum. */
|
|
* (mNumOutputLevels < 2 ? 2 : mNumOutputLevels) /* Number of rows. This should be at least 2 for panning. */
|
|
* (mNumInputLevels < mNumOutputLevels ? mNumOutputLevels : mNumInputLevels) /* Because pan matricies can be [outputlevels][outputlevels] we need to have at least this */
|
|
* sizeof(DSP_LEVEL_TYPE) /* Float values of course. Maybe lower? */
|
|
* 3 /* *3 = mLevel, mLevelCurrent, mLevelDelta */
|
|
+ alignment /* PS3 - 128 byte aligned for DMA */
|
|
);
|
|
}
|
|
}
|
|
|
|
return FMOD_OK;
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#endif
|