Few changes to fix the preload failures

Adds extra error output for erroneous buffer preload
SndStream now correctly sets sndfile to null when it closes, Also extra error reporting around the read function
SFXResource now returns a new threadsaferef each time we openstream. This should only be called on a fresh instance.
This commit is contained in:
marauder2k7 2026-04-06 10:46:04 +01:00
parent d4c0c6fd3d
commit b625250af0
3 changed files with 100 additions and 53 deletions

View file

@ -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;
}

View file

@ -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<SFXResource>& 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;

View file

@ -79,5 +79,9 @@ bool SFXResource::exists( String filename )
ThreadSafeRef<SFXStream> SFXResource::openStream()
{
return mStream;
// Open a fresh independent stream from the file each time
ThreadSafeRef<SFXStream> freshStream = SFXFileStream::create(mFileName);
if (!freshStream)
Con::errorf("SFXResource::openStream() - failed to reopen '%s'", mFileName.c_str());
return freshStream;
}