bool SFXSound::_releaseVoice() { if( !mVoice ) return true; // Refuse to release a voice for a streaming buffer that // is not coming from a profile. For streaming buffers, we will // have to release the buffer, too, and without a profile we don't // know how to recreate the stream. if( isStreaming() && !mTrack ) return false; // If we're currently playing, transfer our playback position // to the playtimer so we can virtualize playback while not // having a voice. SFXStatus status = getLastStatus(); if( status == SFXStatusPlaying || status == SFXStatusBlocked ) { // Sync up the play timer with the voice's current position to make // sure we handle any lag that's cropped up. mPlayTimer.setPosition( mVoice->getPosition() ); if( status == SFXStatusBlocked ) status = SFXStatusPlaying; } mVoice = NULL; // If this is a streaming source, release our buffer, too. // Otherwise the voice will stick around as it is uniquely assigned to // the buffer. When we get reassigned a voice, we will have to do // a full stream seek anyway, so it's no real loss here. if( isStreaming() ) mBuffer = NULL; #ifdef DEBUG_SPEW Platform::outputDebugString( "[SFXSound] release voice for source '%i' (status: %s)", getId(), SFXStatusToString( status ) ); #endif return true; }
void SFXSource::_reloadBuffer() { if( mProfile != NULL && _releaseVoice() ) { SFXBuffer* buffer = mProfile->getBuffer(); if( !buffer ) { Con::errorf( "SFXSource::_reloadBuffer() - Could not create device buffer!" ); return; } _setBuffer( buffer ); if( getLastStatus() == SFXStatusPlaying ) SFX->_assignVoices(); } }
bool SFXSound::_allocVoice( SFXDevice* device ) { // We shouldn't have any existing voice! AssertFatal( !mVoice, "SFXSound::_allocVoice() - Already had a voice!" ); // Must not assign voice to source that isn't playing. AssertFatal( getLastStatus() == SFXStatusPlaying, "SFXSound::_allocVoice() - Source is not playing!" ); // The buffer can be lost when the device is reset // or changed, so initialize it if we have to. If // that fails then we cannot create the voice. if( mBuffer.isNull() ) { SFXProfile* profile = getProfile(); if( profile != NULL ) { SFXBuffer* buffer = profile->getBuffer(); if( buffer ) _setBuffer( buffer ); } if( mBuffer.isNull() ) return false; } // Ask the device for a voice based on this buffer. mVoice = device->createVoice( is3d(), mBuffer ); if( !mVoice ) return false; // Set initial properties. mVoice->setVolume( mPreAttenuatedVolume ); mVoice->setPitch( mEffectivePitch ); mVoice->setPriority( mEffectivePriority ); if( mDescription->mRolloffFactor != -1.f ) mVoice->setRolloffFactor( mDescription->mRolloffFactor ); // Set 3D parameters. if( is3d() ) { // Scatter the position, if requested. Do this only once so // we don't change position when resuming from virtualized // playback. if( !mTransformScattered ) _scatterTransform(); // Set the 3D attributes. setTransform( mTransform ); setVelocity( mVelocity ); _setMinMaxDistance( mMinDistance, mMaxDistance ); _setCone( mConeInsideAngle, mConeOutsideAngle, mConeOutsideVolume ); } // Set reverb, if enabled. if( mDescription->mUseReverb ) mVoice->setReverb( mDescription->mReverb ); // Update the duration... it shouldn't have changed, but // its probably better that we're accurate if it did. mDuration = mBuffer->getDuration(); // If virtualized playback has been started, we transfer its position to the // voice and stop virtualization. const U32 playTime = mPlayTimer.getPosition(); if( playTime > 0 ) { const U32 pos = mBuffer->getFormat().getSampleCount( playTime ); mVoice->setPosition( pos); } mVoice->play( isLooping() ); #ifdef DEBUG_SPEW Platform::outputDebugString( "[SFXSound] allocated voice for source '%i' (pos=%i, 3d=%i, vol=%f)", getId(), playTime, is3d(), mPreAttenuatedVolume ); #endif return true; }
bool SFXSource::_allocVoice( SFXDevice* device ) { // We shouldn't have any existing voice! AssertFatal( !mVoice, "SFXSource::_allocVoice() - Already had a voice!" ); // Must not assign voice to source that isn't playing. AssertFatal( getLastStatus() == SFXStatusPlaying, "SFXSource::_allocVoice() - Source is not playing!" ); // The buffer can be lost when the device is reset // or changed, so initialize it if we have to. If // that fails then we cannot create the voice. if( mBuffer.isNull() ) { if( mProfile != NULL ) _setBuffer( mProfile->getBuffer() ); if( mBuffer.isNull() ) return false; } // Ask the device for a voice based on this buffer. mVoice = device->createVoice( mIs3D, mBuffer ); if( !mVoice ) return false; setVolume( mVolume ); if( mPitch != 1.0f ) setPitch( mPitch ); if( mIs3D ) { setTransform( mTransform ); setVelocity( mVelocity ); setMinMaxDistance( mMinDistance, mMaxDistance ); setCone( mConeInsideAngle, mConeOutsideAngle, mConeOutsideVolume ); } // Update the duration... it shouldn't have changed, but // its probably better that we're accurate if it did. mDuration = mBuffer->getDuration(); // If virtualized playback has been started, we transfer its position to the // voice and stop virtualization. if( mVirtualPlayTimer.isStarted() ) { const U32 playTime = mVirtualPlayTimer.getPosition(); const U32 pos = mBuffer->getFormat().getSampleCount( playTime ); mVoice->setPosition( pos); mVirtualPlayTimer.stop(); } mVoice->play( mIsLooping ); #ifdef DEBUG_SPEW Platform::outputDebugString( "[SFXSource] allocated voice for source '%i'", getId() ); #endif return true; }