#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 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 }