fmodex/fmod/src/fmod_channel_real.cpp

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
}