diff --git a/Engine/source/sfx/media/sfxSndStream.cpp b/Engine/source/sfx/media/sfxSndStream.cpp index eee6d5d69..7dbbca180 100644 --- a/Engine/source/sfx/media/sfxSndStream.cpp +++ b/Engine/source/sfx/media/sfxSndStream.cpp @@ -85,6 +85,7 @@ void SFXSndStream::_close() return; sf_close(sndFile); + sndFile = NULL; } SFXSndStream* SFXSndStream::create(Stream* stream) @@ -99,18 +100,40 @@ SFXSndStream* SFXSndStream::create(Stream* stream) void SFXSndStream::reset() { + if (!sndFile) + return; vio_data.offset = 0; + sf_seek(sndFile, 0, SEEK_SET); } U32 SFXSndStream::read(U8* buffer, U32 length) { if (!sndFile) { - Con::errorf("SFXSndStream - read: Called on uninitialized stream."); + Con::errorf("SFXSndStream - read: Called on uninitialized or closed stream."); + return 0; + } + + if (!buffer) + { + Con::errorf("SFXSndStream - read: NULL buffer passed."); + return 0; + } + + const U32 bytesPerSample = mFormat.getBytesPerSample(); + if (bytesPerSample == 0) + { + Con::errorf("SFXSndStream - read: bytesPerSample is zero, format not initialized?"); + return 0; + } + + U32 framesToRead = length / bytesPerSample; + if (framesToRead == 0) + { + Con::errorf("SFXSndStream - read: length %d too small for bytesPerSample %d", length, bytesPerSample); return 0; } - U32 framesToRead = length / mFormat.getBytesPerSample(); U32 framesRead = 0; switch (sfinfo.format & SF_FORMAT_SUBMASK) @@ -136,11 +159,11 @@ U32 SFXSndStream::read(U8* buffer, U32 length) Con::errorf("SFXSndStream - read: %s", sf_strerror(sndFile)); } - // (convert to frames) - number of frames available < MAX_BUFFER? reset - if (((getPosition() / mFormat.getBytesPerSample()) - sfinfo.frames) < MAX_BUFFER) + sf_count_t currentFrame = sf_seek(sndFile, 0, SEEK_CUR); + if (currentFrame >= sfinfo.frames - (sf_count_t)MAX_BUFFER) { - // reset stream - setPosition(0); + sf_seek(sndFile, 0, SEEK_SET); + vio_data.offset = 0; } diff --git a/Engine/source/sfx/sfxProfile.cpp b/Engine/source/sfx/sfxProfile.cpp index 2af2cb6e2..d8e7875d6 100644 --- a/Engine/source/sfx/sfxProfile.cpp +++ b/Engine/source/sfx/sfxProfile.cpp @@ -275,21 +275,37 @@ void SFXProfile::_onResourceChanged( const Torque::Path& path ) bool SFXProfile::_preloadBuffer() { - AssertFatal( !mDescription->mIsStreaming, "SFXProfile::_preloadBuffer() - must not be called for streaming profiles" ); + AssertFatal(!mDescription->mIsStreaming, "SFXProfile::_preloadBuffer() - must not be called for streaming profiles"); + + if (mFilename == StringTable->EmptyString()) + { + Con::errorf("SFXProfile::_preloadBuffer(%s) - no filename set", getName()); + return false; + } + + Con::printf("SFXProfile::_preloadBuffer(%s) - attempting to preload '%s'", getName(), mFilename); mBuffer = _createBuffer(); - return ( !mBuffer.isNull() ); + if (mBuffer.isNull()) + { + Con::errorf("SFXProfile::_preloadBuffer(%s) - _createBuffer() returned null for '%s'", getName(), mFilename); + return false; + } + + return true; } //----------------------------------------------------------------------------- Resource& SFXProfile::getResource() { - if (!mResource && SFXResource::exists(mFilename)) - mResource = SFXResource::load(mFilename); - else - mResource = NULL; - + if (!mResource) + { + if (SFXResource::exists(mFilename)) + mResource = SFXResource::load(mFilename); + else + Con::errorf("SFXProfile::getResource(%s) - file does not exist: '%s'", getName(), mFilename); + } return mResource; } @@ -317,47 +333,51 @@ SFXBuffer* SFXProfile::getBuffer() SFXBuffer* SFXProfile::_createBuffer() { - SFXBuffer* buffer = 0; - - // Try to create through SFXDevie. - - if( mFilename != StringTable->EmptyString() && SFX ) - { - buffer = SFX->_createBuffer( mFilename, mDescription ); - if( buffer ) - { - #ifdef TORQUE_DEBUG - const SFXFormat& format = buffer->getFormat(); - Con::printf( "%s SFX: %s (%i channels, %i kHz, %.02f sec, %i kb)", - mDescription->mIsStreaming ? "Streaming" : "Loaded", mFilename, - format.getChannels(), - format.getSamplesPerSecond() / 1000, - F32( buffer->getDuration() ) / 1000.0f, - format.getDataLength( buffer->getDuration() ) / 1024 ); - #endif - } - } - - // If that failed, load through SFXResource. - - if( !buffer ) - { - Resource< SFXResource >& resource = getResource(); - if( resource != NULL && SFX ) - { - #ifdef TORQUE_DEBUG - const SFXFormat& format = resource->getFormat(); - Con::printf( "%s SFX: %s (%i channels, %i kHz, %.02f sec, %i kb)", - mDescription->mIsStreaming ? "Streaming" : "Loading", resource->getFileName().c_str(), - format.getChannels(), - format.getSamplesPerSecond(), - F32( resource->getDuration() ) / 1000.0f, - format.getDataLength( resource->getDuration() ) / 1024 ); - #endif + SFXBuffer* buffer = NULL; - ThreadSafeRef< SFXStream > sfxStream = resource->openStream(); - buffer = SFX->_createBuffer( sfxStream, mDescription ); + if (mFilename == StringTable->EmptyString()) + { + Con::errorf("SFXProfile::_createBuffer(%s) - mFilename is empty!", getName()); + return NULL; + } + + if (!SFX) + { + Con::errorf("SFXProfile::_createBuffer(%s) - No SFX system available!", getName()); + return NULL; + } + + // Try to create through SFXDevice. For now this always fails and i think was just here for historical reasons. Function just returns null. + /*buffer = SFX->_createBuffer(mFilename, mDescription); + if (!buffer) + Con::warnf("SFXProfile::_createBuffer(%s) - Device _createBuffer from filename failed, falling back to SFXResource.", getName());*/ + + // If that failed, load through SFXResource. + if (!buffer) + { + if (!SFXResource::exists(mFilename)) + { + Con::errorf("SFXProfile::_createBuffer(%s) - SFXResource::exists() returned false for '%s'", getName(), mFilename); + return NULL; } + + Resource< SFXResource >& resource = getResource(); + if (resource == NULL) + { + Con::errorf("SFXProfile::_createBuffer(%s) - getResource() returned NULL for '%s'", getName(), mFilename); + return NULL; + } + + ThreadSafeRef< SFXStream > sfxStream = resource->openStream(); + if (!sfxStream) + { + Con::errorf("SFXProfile::_createBuffer(%s) - openStream() returned NULL for '%s'", getName(), mFilename); + return NULL; + } + + buffer = SFX->_createBuffer(sfxStream, mDescription); + if (!buffer) + Con::errorf("SFXProfile::_createBuffer(%s) - Device _createBuffer from stream also failed for '%s'", getName(), mFilename); } return buffer; diff --git a/Engine/source/sfx/sfxResource.cpp b/Engine/source/sfx/sfxResource.cpp index fa03a9a58..6f03867aa 100644 --- a/Engine/source/sfx/sfxResource.cpp +++ b/Engine/source/sfx/sfxResource.cpp @@ -79,5 +79,9 @@ bool SFXResource::exists( String filename ) ThreadSafeRef SFXResource::openStream() { - return mStream; + // Open a fresh independent stream from the file each time + ThreadSafeRef freshStream = SFXFileStream::create(mFileName); + if (!freshStream) + Con::errorf("SFXResource::openStream() - failed to reopen '%s'", mFileName.c_str()); + return freshStream; }