1600 lines
27 KiB
C++
Executable file
1600 lines
27 KiB
C++
Executable file
#include "fmod_settings.h"
|
|
|
|
#include "fmod_3d.h"
|
|
#include "fmod_channel_real.h"
|
|
#include "fmod_channeli.h"
|
|
#include "fmod_channelpool.h"
|
|
#include "fmod_output.h"
|
|
#include "fmod_systemi.h"
|
|
#include "fmod_soundi.h"
|
|
#include "fmod_speakermap.h"
|
|
|
|
#include <string.h>
|
|
|
|
namespace FMOD
|
|
{
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
ChannelReal::ChannelReal()
|
|
{
|
|
mSound = 0;
|
|
mSystem = 0;
|
|
mOutput = 0;
|
|
mPool = 0;
|
|
mLoopCount = -1;
|
|
mMinFrequency = 100.0f;
|
|
mMaxFrequency = 1000000.0f;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT ChannelReal::init(int index, SystemI *system, Output *output, DSPI *dspmixtarget)
|
|
{
|
|
mSound = 0;
|
|
mFlags = (CHANNELREAL_FLAG)0;
|
|
mMode = (FMOD_MODE)0;
|
|
mPosition = 0;
|
|
mDirection = CHANNELREAL_PLAYDIR_FORWARDS;
|
|
mLoopCount = -1;
|
|
mOutput = output;
|
|
mSystem = system;
|
|
mIndex = index;
|
|
|
|
#ifdef PLATFORM_WII
|
|
mControllerSpeaker = 0;
|
|
mBiquadActive = false;
|
|
mBiquadB0 = 0;
|
|
mBiquadB1 = 0;
|
|
mBiquadB2 = 0;
|
|
mBiquadA1 = 0;
|
|
mBiquadA2 = 0;
|
|
mLPFCutoff = -1;
|
|
#endif
|
|
|
|
return FMOD_OK;
|
|
}
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT ChannelReal::close()
|
|
{
|
|
return stop();
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT ChannelReal::alloc()
|
|
{
|
|
mPosition = 0;
|
|
|
|
if (mPool)
|
|
{
|
|
mPool->mChannelsUsed++;
|
|
}
|
|
|
|
return FMOD_OK;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT ChannelReal::alloc(DSPI *dsp)
|
|
{
|
|
if (mPool)
|
|
{
|
|
mPool->mChannelsUsed++;
|
|
}
|
|
|
|
mPosition = 0;
|
|
|
|
return FMOD_OK;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT ChannelReal::set2DFreqVolumePanFor3D()
|
|
{
|
|
/*
|
|
Channel types that have their own 3d system (ie dsound3d or xbox) will call this,
|
|
software and others use the stereo panning method defined in ChannelRealManual3D.
|
|
*/
|
|
return FMOD_OK;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT ChannelReal::update(int delta)
|
|
{
|
|
return FMOD_OK;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT ChannelReal::updateStream()
|
|
{
|
|
return FMOD_OK;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT ChannelReal::start()
|
|
{
|
|
return FMOD_OK;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT ChannelReal::stop()
|
|
{
|
|
// mSound = 0; /* ChannelI or ChannelStream will clear this out in its stop call. */
|
|
// mDSP = 0; /* ChannelI or ChannelStream will clear this out in its stop call. */
|
|
|
|
if (mPool) /* Channel might not belong to a pool */
|
|
{
|
|
mPool->mChannelsUsed--;
|
|
}
|
|
|
|
mFlags = (CHANNELREAL_FLAG)(mFlags & ~CHANNELREAL_FLAG_ALLOCATED);
|
|
mFlags = (CHANNELREAL_FLAG)(mFlags & ~CHANNELREAL_FLAG_PLAYING);
|
|
mFlags = (CHANNELREAL_FLAG)(mFlags & ~CHANNELREAL_FLAG_PAUSED);
|
|
|
|
mFlags = (CHANNELREAL_FLAG)(mFlags | CHANNELREAL_FLAG_STOPPED);
|
|
|
|
#ifdef PLATFORM_WII
|
|
mControllerSpeaker = 0;
|
|
mBiquadActive = false;
|
|
mBiquadB0 = 0;
|
|
mBiquadB1 = 0;
|
|
mBiquadB2 = 0;
|
|
mBiquadA1 = 0;
|
|
mBiquadA2 = 0;
|
|
mLPFCutoff = -1;
|
|
#endif
|
|
|
|
return FMOD_OK;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT ChannelReal::setPaused(bool paused)
|
|
{
|
|
if (paused)
|
|
{
|
|
mFlags = (CHANNELREAL_FLAG)(mFlags | CHANNELREAL_FLAG_PAUSED);
|
|
}
|
|
else
|
|
{
|
|
mFlags = (CHANNELREAL_FLAG)(mFlags & ~CHANNELREAL_FLAG_PAUSED);
|
|
}
|
|
|
|
return FMOD_OK;
|
|
}
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT ChannelReal::getPaused(bool *paused)
|
|
{
|
|
if (!paused)
|
|
{
|
|
return FMOD_ERR_INVALID_PARAM;
|
|
}
|
|
|
|
*paused = mFlags & CHANNELREAL_FLAG_PAUSED ? true : false;
|
|
|
|
return FMOD_OK;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT ChannelReal::setVolume(float volume)
|
|
{
|
|
return FMOD_OK;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT ChannelReal::setFrequency(float frequency)
|
|
{
|
|
return FMOD_OK;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT ChannelReal::setPan(float pan, float fbpan)
|
|
{
|
|
return FMOD_OK;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT ChannelReal::setDSPClockDelay()
|
|
{
|
|
return FMOD_OK;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT ChannelReal::setSpeakerMix(float frontleft, float frontright, float center, float lfe, float backleft, float backright, float sideleft, float sideright)
|
|
{
|
|
int numsubchannels = 0;
|
|
|
|
if (mDSP)
|
|
{
|
|
return FMOD_OK; /* Only ChannelSoftware supports DSP. */
|
|
}
|
|
|
|
if (mSound)
|
|
{
|
|
if (mSound->mSubSampleParent)
|
|
{
|
|
numsubchannels = mSound->mSubSampleParent->mChannels;
|
|
}
|
|
else
|
|
{
|
|
numsubchannels = mSound->mChannels;
|
|
}
|
|
}
|
|
|
|
if (numsubchannels > 1)
|
|
{
|
|
if (mSound->mDefaultChannelMask & SPEAKER_ALLMONO)
|
|
{
|
|
setPan(0.0f, 1.0f);
|
|
setVolume(center * mParent->mVolume);
|
|
}
|
|
else if (mSound->mDefaultChannelMask & SPEAKER_ALLSTEREO)
|
|
{
|
|
switch (mSubChannelIndex % 2)
|
|
{
|
|
case 0:
|
|
{
|
|
setPan(-1.0f, 1.0f);
|
|
setVolume(frontleft * mParent->mVolume);
|
|
break;
|
|
}
|
|
case 1:
|
|
{
|
|
setPan(1.0f, 1.0f);
|
|
setVolume(frontright * mParent->mVolume);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch (mSubChannelIndex)
|
|
{
|
|
case 0:
|
|
{
|
|
setPan(-1.0f, 1.0f);
|
|
setVolume(frontleft * mParent->mVolume);
|
|
break;
|
|
}
|
|
case 1:
|
|
{
|
|
setPan(1.0f, 1.0f);
|
|
setVolume(frontright * mParent->mVolume);
|
|
break;
|
|
}
|
|
case 2:
|
|
{
|
|
setPan(0.0f, 1.0f);
|
|
setVolume(center * mParent->mVolume);
|
|
break;
|
|
}
|
|
case 3:
|
|
{
|
|
setPan(0.0f, 0.0f);
|
|
setVolume(lfe * mParent->mVolume);
|
|
break;
|
|
}
|
|
case 4:
|
|
{
|
|
setPan(-1.0f, -1.0f);
|
|
setVolume(backleft * mParent->mVolume);
|
|
break;
|
|
}
|
|
case 5:
|
|
{
|
|
setPan(1.0f, -1.0f);
|
|
setVolume(backright * mParent->mVolume);
|
|
break;
|
|
}
|
|
case 6:
|
|
{
|
|
setPan(-1.0f, 0.0f);
|
|
setVolume(sideleft * mParent->mVolume);
|
|
break;
|
|
}
|
|
case 7:
|
|
{
|
|
setPan(1.0f, 0.0f);
|
|
setVolume(sideright * mParent->mVolume);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
float vol = 0, lrpan = 0, fbpan = 0;
|
|
|
|
vol += frontleft;
|
|
vol += frontright;
|
|
vol += center;
|
|
vol += lfe;
|
|
vol += backleft;
|
|
vol += backright;
|
|
vol += sideleft;
|
|
vol += sideright;
|
|
|
|
#if 0
|
|
|
|
float sqrtsumsq;
|
|
/*
|
|
Normalise
|
|
*/
|
|
sqrtsumsq = frontleft*frontleft + frontright*frontright + backleft*backleft + backright*backright + sideleft*sideleft + sideright*sideright;
|
|
sqrtsumsq = FMOD_SQRT(sqrtsumsq);
|
|
|
|
lrpan -= frontleft / sqrtsumsq;
|
|
lrpan += frontright / sqrtsumsq;
|
|
lrpan -= backleft / sqrtsumsq;
|
|
lrpan += backright / sqrtsumsq;
|
|
lrpan -= sideleft / sqrtsumsq;
|
|
lrpan += sideright / sqrtsumsq;
|
|
|
|
/*
|
|
Normalise
|
|
*/
|
|
sqrtsumsq = frontleft*frontleft + frontright*frontright + backleft*backleft + backright*backright + center*center;
|
|
sqrtsumsq = FMOD_SQRT(sqrtsumsq);
|
|
|
|
fbpan += frontleft / sqrtsumsq;
|
|
fbpan += frontright / sqrtsumsq;
|
|
fbpan += center / sqrtsumsq;
|
|
fbpan -= backleft / sqrtsumsq;
|
|
fbpan -= backright / sqrtsumsq;
|
|
|
|
#else
|
|
|
|
lrpan -= frontleft;
|
|
lrpan += frontright;
|
|
lrpan -= backleft;
|
|
lrpan += backright;
|
|
lrpan -= sideleft;
|
|
lrpan += sideright;
|
|
|
|
fbpan += frontleft;
|
|
fbpan += frontright;
|
|
fbpan += center;
|
|
fbpan -= backleft;
|
|
fbpan -= backright;
|
|
|
|
#endif
|
|
|
|
vol = vol > 1.0f ? 1.0f : vol;
|
|
setVolume(vol * mParent->mVolume);
|
|
setPan(lrpan < -1.0f ? -1.0f : lrpan > 1.0f ? 1.0f : lrpan,
|
|
fbpan < -1.0f ? -1.0f : fbpan > 1.0f ? 1.0f : fbpan);
|
|
}
|
|
|
|
return FMOD_OK;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT ChannelReal::setSpeakerLevels(int speaker, float *levels, int numlevels)
|
|
{
|
|
if (!mParent)
|
|
{
|
|
return FMOD_OK;
|
|
}
|
|
|
|
if (!mParent->mLevels)
|
|
{
|
|
mSystem->mSpeakerLevelsPool.alloc(&mParent->mLevels);
|
|
if (!mParent->mLevels)
|
|
{
|
|
return FMOD_ERR_MEMORY;
|
|
}
|
|
}
|
|
|
|
for (int count = 0; count < numlevels; count++)
|
|
{
|
|
float volume = levels[count];
|
|
|
|
if (volume < 0)
|
|
{
|
|
volume = 0;
|
|
}
|
|
if (volume > 1.0f)
|
|
{
|
|
volume = 1.0f;
|
|
}
|
|
|
|
mParent->mLevels[(speaker * mSystem->mMaxInputChannels) + count] = volume;
|
|
}
|
|
|
|
|
|
return updateSpeakerLevels(mParent->mVolume);
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT ChannelReal::updateSpeakerLevels(float volume)
|
|
{
|
|
if (mParent && mParent->mLevels)
|
|
{
|
|
int count;
|
|
float vol = 0, pan = 0, fbpan = 0;
|
|
float sumsq = 0.0f, sqrtsumsq;
|
|
int outputchannels = mSystem->mMaxOutputChannels;
|
|
|
|
if (mParent->mSpeakerMode == FMOD_SPEAKERMODE_PROLOGIC)
|
|
{
|
|
outputchannels = 6;
|
|
}
|
|
|
|
for (count = 0; count < outputchannels; count++)
|
|
{
|
|
if (count == FMOD_SPEAKER_FRONT_CENTER || count == FMOD_SPEAKER_LOW_FREQUENCY)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
float val = FMOD_FABS(mParent->mLevels[(count * mSystem->mMaxInputChannels) + mSubChannelIndex]);
|
|
|
|
sumsq += val*val;
|
|
}
|
|
|
|
sqrtsumsq = FMOD_SQRT(sumsq);
|
|
vol = sqrtsumsq;
|
|
|
|
for (count = 0; count < outputchannels; count++)
|
|
{
|
|
float val = FMOD_FABS(mParent->mLevels[(count * mSystem->mMaxInputChannels) + mSubChannelIndex]);
|
|
|
|
if (sqrtsumsq)
|
|
{
|
|
val /= sqrtsumsq;
|
|
}
|
|
else
|
|
{
|
|
val = 0;
|
|
}
|
|
|
|
if (count == FMOD_SPEAKER_FRONT_LEFT || count == FMOD_SPEAKER_BACK_LEFT || count == FMOD_SPEAKER_SIDE_LEFT)
|
|
{
|
|
pan -= val;
|
|
}
|
|
else if (count == FMOD_SPEAKER_FRONT_RIGHT || count == FMOD_SPEAKER_BACK_RIGHT || count == FMOD_SPEAKER_SIDE_RIGHT)
|
|
{
|
|
pan += val;
|
|
}
|
|
|
|
if (count == FMOD_SPEAKER_FRONT_LEFT || count == FMOD_SPEAKER_FRONT_RIGHT )
|
|
{
|
|
fbpan += val;
|
|
}
|
|
else if (count == FMOD_SPEAKER_BACK_LEFT || count == FMOD_SPEAKER_BACK_RIGHT)
|
|
{
|
|
fbpan -= val;
|
|
}
|
|
}
|
|
|
|
vol = vol > 1.0f ? 1.0f : vol;
|
|
setVolume(vol * volume);
|
|
setPan(pan < -1.0f ? -1.0f : pan > 1.0f ? 1.0f : pan, fbpan < -1.0f ? -1.0f : fbpan > 1.0f ? 1.0f : fbpan);
|
|
}
|
|
|
|
return FMOD_OK;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT ChannelReal::setPosition(unsigned int position, FMOD_TIMEUNIT postype)
|
|
{
|
|
if (postype != FMOD_TIMEUNIT_MS && postype != FMOD_TIMEUNIT_PCM && postype != FMOD_TIMEUNIT_PCMBYTES)
|
|
{
|
|
return FMOD_ERR_FORMAT;
|
|
}
|
|
|
|
if (mSound)
|
|
{
|
|
FMOD_RESULT result;
|
|
unsigned int pcm = 0, lengthpcm;
|
|
|
|
result = mSound->getLength(&lengthpcm, FMOD_TIMEUNIT_PCM);
|
|
if (result != FMOD_OK)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
if (postype == FMOD_TIMEUNIT_PCM)
|
|
{
|
|
pcm = position;
|
|
}
|
|
else if (postype == FMOD_TIMEUNIT_PCMBYTES)
|
|
{
|
|
SoundI::getSamplesFromBytes(position, &pcm, mSound->mChannels, mSound->mFormat);
|
|
}
|
|
else if (postype == FMOD_TIMEUNIT_MS)
|
|
{
|
|
pcm = (unsigned int)((float)position / 1000.0f * mSound->mDefaultFrequency);
|
|
}
|
|
|
|
if (pcm >= lengthpcm)
|
|
{
|
|
pcm = lengthpcm;
|
|
}
|
|
|
|
mPosition = pcm;
|
|
}
|
|
|
|
|
|
return FMOD_OK;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT ChannelReal::getPosition(unsigned int *position, FMOD_TIMEUNIT postype)
|
|
{
|
|
bool getsubsoundtime = false;
|
|
|
|
if (!position)
|
|
{
|
|
return FMOD_ERR_INVALID_PARAM;
|
|
}
|
|
|
|
if (!mSound)
|
|
{
|
|
return FMOD_ERR_INVALID_PARAM;
|
|
}
|
|
|
|
postype = (FMOD_TIMEUNIT)(postype & ~FMOD_TIMEUNIT_BUFFERED); /* Not a stream, so buffering is irrelevant. */
|
|
|
|
/*
|
|
First check for sentence stuff.
|
|
*/
|
|
if (postype == FMOD_TIMEUNIT_SENTENCE_MS)
|
|
{
|
|
postype = FMOD_TIMEUNIT_MS;
|
|
getsubsoundtime = true;
|
|
}
|
|
else if (postype == FMOD_TIMEUNIT_SENTENCE_PCM)
|
|
{
|
|
postype = FMOD_TIMEUNIT_PCM;
|
|
getsubsoundtime = true;
|
|
}
|
|
else if (postype == FMOD_TIMEUNIT_SENTENCE_PCMBYTES)
|
|
{
|
|
postype = FMOD_TIMEUNIT_PCMBYTES;
|
|
getsubsoundtime = true;
|
|
}
|
|
else if (postype == FMOD_TIMEUNIT_SENTENCE || postype == FMOD_TIMEUNIT_SENTENCE_SUBSOUND)
|
|
{
|
|
getsubsoundtime = true;
|
|
}
|
|
|
|
if (getsubsoundtime
|
|
#ifdef FMOD_SUPPORT_SENTENCING
|
|
&& !mSound->mSubSoundList
|
|
#endif
|
|
)
|
|
{
|
|
return FMOD_ERR_INVALID_PARAM;
|
|
}
|
|
|
|
if (postype == FMOD_TIMEUNIT_MS || postype == FMOD_TIMEUNIT_PCM || postype == FMOD_TIMEUNIT_PCMBYTES || postype == FMOD_TIMEUNIT_SENTENCE || postype == FMOD_TIMEUNIT_SENTENCE_SUBSOUND)
|
|
{
|
|
int currentsubsoundid = 0;
|
|
int currentsentenceid = 0;
|
|
unsigned int pcmcurrent = mPosition;
|
|
|
|
#ifdef FMOD_SUPPORT_SENTENCING
|
|
if (getsubsoundtime)
|
|
{
|
|
for (currentsubsoundid = 0; currentsubsoundid < mSound->mSubSoundListNum; currentsubsoundid++)
|
|
{
|
|
SoundI *sound = mSound->mSubSound[mSound->mSubSoundList[currentsubsoundid].mIndex];
|
|
|
|
if (sound && pcmcurrent >= sound->mLength)
|
|
{
|
|
pcmcurrent -= sound->mLength;
|
|
currentsentenceid++;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if (postype == FMOD_TIMEUNIT_SENTENCE)
|
|
{
|
|
*position = currentsentenceid;
|
|
}
|
|
else if (postype == FMOD_TIMEUNIT_SENTENCE_SUBSOUND)
|
|
{
|
|
*position = currentsubsoundid;
|
|
}
|
|
else if (postype == FMOD_TIMEUNIT_PCM)
|
|
{
|
|
*position = pcmcurrent;
|
|
}
|
|
else if (postype == FMOD_TIMEUNIT_PCMBYTES)
|
|
{
|
|
SoundI::getBytesFromSamples(pcmcurrent, position, mSound->mChannels, mSound->mFormat);
|
|
}
|
|
else if (postype == FMOD_TIMEUNIT_MS)
|
|
{
|
|
*position = (unsigned int)((float)pcmcurrent / mSound->mDefaultFrequency * 1000.0f);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return FMOD_ERR_FORMAT;
|
|
}
|
|
|
|
return FMOD_OK;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT ChannelReal::setLoopPoints(unsigned int loopstart, unsigned int looplength)
|
|
{
|
|
if (!mSound)
|
|
{
|
|
return FMOD_ERR_INVALID_PARAM;
|
|
}
|
|
|
|
if (loopstart >= mSound->mLength)
|
|
{
|
|
return FMOD_ERR_INVALID_PARAM;
|
|
}
|
|
if (loopstart + looplength > mSound->mLength)
|
|
{
|
|
return FMOD_ERR_INVALID_PARAM;
|
|
}
|
|
|
|
mLoopStart = loopstart;
|
|
mLoopLength = looplength;
|
|
|
|
return FMOD_OK;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
Win32, Win64, Linux, Macintosh, XBox, PlayStation 2, GameCube
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT ChannelReal::setLoopCount(int loopcount)
|
|
{
|
|
mLoopCount = loopcount;
|
|
|
|
return FMOD_OK;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT ChannelReal::setLowPassGain(float gain)
|
|
{
|
|
return FMOD_OK;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT ChannelReal::set3DAttributes()
|
|
{
|
|
return FMOD_OK;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT ChannelReal::set3DMinMaxDistance()
|
|
{
|
|
return FMOD_OK;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT ChannelReal::set3DOcclusion(float directOcclusion, float reverbOcclusion)
|
|
{
|
|
if (!mParent)
|
|
{
|
|
return FMOD_OK;
|
|
}
|
|
|
|
return setVolume(mParent->mVolume);
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT ChannelReal::setReverbProperties(const FMOD_REVERB_CHANNELPROPERTIES *prop)
|
|
{
|
|
#ifndef FMOD_STATICFORPLUGINS
|
|
if (!prop)
|
|
{
|
|
return FMOD_ERR_INVALID_PARAM;
|
|
}
|
|
|
|
/*
|
|
Set the reverb's channel properties and update the reverb mix
|
|
*/
|
|
if (!mParent)
|
|
{
|
|
return FMOD_OK;
|
|
}
|
|
|
|
FMOD_RESULT result;
|
|
int instance, numinstances = 0;
|
|
for (instance = 0; instance < FMOD_REVERB_MAXINSTANCES; instance++)
|
|
{
|
|
if (prop->Flags & (FMOD_REVERB_CHANNELFLAGS_INSTANCE0 << instance))
|
|
{
|
|
numinstances++;
|
|
}
|
|
}
|
|
|
|
for (instance = 0; instance < FMOD_REVERB_MAXINSTANCES; instance++)
|
|
{
|
|
if (prop->Flags & (FMOD_REVERB_CHANNELFLAGS_INSTANCE0 << instance) || (!numinstances && !instance))
|
|
{
|
|
result = mSystem->mReverbGlobal.setChanProperties(instance, mParent->mIndex, prop);
|
|
if (numinstances <= 1 && result != FMOD_OK)
|
|
{
|
|
return result;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// update direct mix on other instances (ignoring errors)
|
|
FMOD_REVERB_CHANNELPROPERTIES cprop;
|
|
result = mSystem->mReverbGlobal.getChanProperties(instance, mParent->mIndex, &cprop);
|
|
cprop.Direct = prop->Direct;
|
|
result = mSystem->mReverbGlobal.setChanProperties(instance, mParent->mIndex, &cprop);
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
return FMOD_OK;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT ChannelReal::getReverbProperties(FMOD_REVERB_CHANNELPROPERTIES *prop)
|
|
{
|
|
#ifndef FMOD_STATICFORPLUGINS
|
|
|
|
if(!prop)
|
|
{
|
|
return FMOD_ERR_INVALID_PARAM;
|
|
}
|
|
|
|
if (!mParent)
|
|
{
|
|
return FMOD_OK;
|
|
}
|
|
|
|
int instance = (prop->Flags & FMOD_REVERB_CHANNELFLAGS_INSTANCE1) ? 1 :
|
|
(prop->Flags & FMOD_REVERB_CHANNELFLAGS_INSTANCE2) ? 2 :
|
|
(prop->Flags & FMOD_REVERB_CHANNELFLAGS_INSTANCE3) ? 3 :
|
|
0;
|
|
|
|
return mSystem->mReverbGlobal.getChanProperties(instance, mParent->mIndex, prop, 0);
|
|
|
|
#endif
|
|
|
|
return FMOD_OK;
|
|
}
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT ChannelReal::isPlaying(bool *isplaying, bool includethreadlatency)
|
|
{
|
|
if (!isplaying)
|
|
{
|
|
return FMOD_ERR_INVALID_PARAM;
|
|
}
|
|
|
|
if (mFlags & CHANNELREAL_FLAG_PLAYING || mFlags & CHANNELREAL_FLAG_ALLOCATED)
|
|
{
|
|
*isplaying = true;
|
|
}
|
|
else
|
|
{
|
|
*isplaying = false;
|
|
}
|
|
|
|
return FMOD_OK;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT ChannelReal::isVirtual(bool *isvirtual)
|
|
{
|
|
if (!isvirtual)
|
|
{
|
|
return FMOD_ERR_INVALID_PARAM;
|
|
}
|
|
|
|
*isvirtual = false;
|
|
|
|
return FMOD_OK;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT ChannelReal::getSpectrum(float *spectrumarray, int numentries, int channeloffset, FMOD_DSP_FFT_WINDOW windowtype)
|
|
{
|
|
return FMOD_ERR_NEEDSSOFTWARE;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT ChannelReal::getWaveData(float *wavearray, int numvalues, int channeloffset)
|
|
{
|
|
return FMOD_ERR_NEEDSSOFTWARE;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT ChannelReal::getDSPHead(DSPI **dsp)
|
|
{
|
|
*dsp = 0;
|
|
|
|
return FMOD_ERR_NEEDSSOFTWARE;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT ChannelReal::setMode(FMOD_MODE mode)
|
|
{
|
|
/*
|
|
Allow switching between loop modes.
|
|
*/
|
|
if (mode & (FMOD_LOOP_OFF | FMOD_LOOP_NORMAL | FMOD_LOOP_BIDI))
|
|
{
|
|
mMode = mMode & ~(FMOD_LOOP_OFF | FMOD_LOOP_NORMAL | FMOD_LOOP_BIDI);
|
|
|
|
if (mode & FMOD_LOOP_OFF)
|
|
{
|
|
mMode |= FMOD_LOOP_OFF;
|
|
}
|
|
else if (mode & FMOD_LOOP_NORMAL)
|
|
{
|
|
mMode |= FMOD_LOOP_NORMAL;
|
|
}
|
|
else if (mode & FMOD_LOOP_BIDI)
|
|
{
|
|
mMode |= FMOD_LOOP_BIDI;
|
|
}
|
|
}
|
|
|
|
/*
|
|
Allow switching between head relative and world relative.
|
|
*/
|
|
if (mode & FMOD_3D_HEADRELATIVE)
|
|
{
|
|
mMode &= ~FMOD_3D_WORLDRELATIVE;
|
|
mMode |= FMOD_3D_HEADRELATIVE;
|
|
}
|
|
else if (mode & FMOD_3D_WORLDRELATIVE)
|
|
{
|
|
mMode &= ~FMOD_3D_HEADRELATIVE;
|
|
mMode |= FMOD_3D_WORLDRELATIVE;
|
|
}
|
|
|
|
/*
|
|
Allow switching between linear/log/custom rolloff.
|
|
*/
|
|
if (mode & FMOD_3D_LOGROLLOFF)
|
|
{
|
|
mMode &= ~FMOD_3D_LINEARROLLOFF;
|
|
mMode &= ~FMOD_3D_CUSTOMROLLOFF;
|
|
mMode |= FMOD_3D_LOGROLLOFF;
|
|
}
|
|
else if (mode & FMOD_3D_LINEARROLLOFF)
|
|
{
|
|
mMode &= ~FMOD_3D_LOGROLLOFF;
|
|
mMode &= ~FMOD_3D_CUSTOMROLLOFF;
|
|
mMode |= FMOD_3D_LINEARROLLOFF;
|
|
}
|
|
else if (mode & FMOD_3D_CUSTOMROLLOFF)
|
|
{
|
|
mMode &= ~FMOD_3D_LOGROLLOFF;
|
|
mMode &= ~FMOD_3D_LINEARROLLOFF;
|
|
mMode |= FMOD_3D_CUSTOMROLLOFF;
|
|
}
|
|
|
|
if (mode & FMOD_3D_IGNOREGEOMETRY)
|
|
{
|
|
mMode |= FMOD_3D_IGNOREGEOMETRY;
|
|
}
|
|
else
|
|
{
|
|
mMode &= ~FMOD_3D_IGNOREGEOMETRY;
|
|
}
|
|
|
|
if (mode & FMOD_VIRTUAL_PLAYFROMSTART)
|
|
{
|
|
mMode |= FMOD_VIRTUAL_PLAYFROMSTART;
|
|
}
|
|
else
|
|
{
|
|
mMode &= ~FMOD_VIRTUAL_PLAYFROMSTART;
|
|
}
|
|
|
|
/*
|
|
Allow switching between 2D and 3D only in software.
|
|
*/
|
|
#if !defined( PLATFORM_GC ) && !defined( PLATFORM_WII ) && !defined( PLATFORM_PSP ) && !defined( PLATFORM_PS2 )
|
|
if (!(mMode & FMOD_HARDWARE))
|
|
#endif
|
|
{
|
|
if (mode & FMOD_2D)
|
|
{
|
|
if (!mParent)
|
|
{
|
|
return FMOD_OK;
|
|
}
|
|
|
|
mMode &= ~FMOD_3D;
|
|
mMode |= FMOD_2D;
|
|
mParent->mVolume3D = 1.0f;
|
|
mParent->mDirectOcclusion = 0.0f;
|
|
mParent->mReverbDryVolume = 1.0f;
|
|
mParent->mConeVolume3D = 1.0f;
|
|
mParent->mPitch3D = 1.0f;
|
|
}
|
|
else if (mode & FMOD_3D)
|
|
{
|
|
mMode &= ~FMOD_2D;
|
|
mMode |= FMOD_3D;
|
|
}
|
|
}
|
|
|
|
return FMOD_OK;
|
|
}
|
|
|
|
|
|
#ifdef PLATFORM_WII
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT ChannelReal::setLowPassFilter(int cutoff)
|
|
{
|
|
mLPFCutoff = cutoff;
|
|
|
|
return FMOD_OK;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT ChannelReal::getLowPassFilter(int *cutoff)
|
|
{
|
|
*cutoff = mLPFCutoff;
|
|
|
|
return FMOD_OK;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT ChannelReal::setBiquadFilter(bool active, unsigned short b0, unsigned short b1, unsigned short b2, unsigned short a1, unsigned short a2)
|
|
{
|
|
mBiquadActive = active;
|
|
mBiquadB0 = b0;
|
|
mBiquadB1 = b1;
|
|
mBiquadB2 = b2;
|
|
mBiquadA1 = a1;
|
|
mBiquadA2 = a2;
|
|
|
|
return FMOD_OK;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT ChannelReal::getBiquadFilter(bool *active, unsigned short *b0, unsigned short *b1, unsigned short *b2, unsigned short *a1, unsigned short *a2)
|
|
{
|
|
*active = mBiquadActive;
|
|
*b0 = mBiquadB0;
|
|
*b1 = mBiquadB1;
|
|
*b2 = mBiquadB2;
|
|
*a1 = mBiquadA1;
|
|
*a2 = mBiquadA2;
|
|
|
|
return FMOD_OK;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT ChannelReal::setControllerSpeaker(unsigned int controllerspeaker, int subchannel)
|
|
{
|
|
mControllerSpeaker = controllerspeaker;
|
|
|
|
return FMOD_OK;
|
|
}
|
|
|
|
|
|
/*
|
|
[
|
|
[DESCRIPTION]
|
|
|
|
[PARAMETERS]
|
|
|
|
[RETURN_VALUE]
|
|
|
|
[REMARKS]
|
|
|
|
[PLATFORMS]
|
|
|
|
[SEE_ALSO]
|
|
]
|
|
*/
|
|
FMOD_RESULT ChannelReal::getControllerSpeaker(unsigned int *controllerspeaker)
|
|
{
|
|
*controllerspeaker = mControllerSpeaker;
|
|
|
|
return FMOD_OK;
|
|
}
|
|
#endif
|
|
|
|
}
|
|
|
|
|