bool plWin32StaticSound::LoadSound( bool is3D ) { if (fFailed) return false; if( fPriority > plgAudioSys::GetPriorityCutoff() ) return false; // Don't set the failed flag, just return if (plgAudioSys::Active() && !fDSoundBuffer) { // Debug flag #1 if( fChannelSelect > 0 && plgAudioSys::IsDebugFlagSet( plgAudioSys::kDisableRightSelect ) ) { // Force a fail fFailed = true; return false; } // We need it to be resident to read in plSoundBuffer::ELoadReturnVal retVal = IPreLoadBuffer(true); plSoundBuffer *buffer = (plSoundBuffer *)fDataBufferKey->ObjectIsLoaded(); if(!buffer) { return plSoundBuffer::kError; } if( retVal == plSoundBuffer::kPending) // we are still reading data. { return true; } if( retVal == plSoundBuffer::kError ) { plString str = plFormat("Unable to open .wav file {}", fDataBufferKey ? fDataBufferKey->GetName() : "nil"); IPrintDbgMessage( str.c_str(), true ); fFailed = true; return false; } SetProperty( kPropIs3DSound, is3D ); plWAVHeader header = buffer->GetHeader(); // Debug flag #2 if( fChannelSelect == 0 && header.fNumChannels > 1 && plgAudioSys::IsDebugFlagSet( plgAudioSys::kDisableLeftSelect ) ) { // Force a fail fFailed = true; return false; } uint32_t bufferSize = buffer->GetDataLength(); if( header.fNumChannels > 1 && is3D ) { // We can only do a single channel of 3D sound. So copy over one (later) bufferSize /= header.fNumChannels; header.fBlockAlign /= header.fNumChannels; header.fAvgBytesPerSec /= header.fNumChannels; header.fNumChannels = 1; } bool tryStatic = true; // If we want FX, we can't use a static voice, but EAX doesn't fit under that limitation :) if( 0 ) tryStatic = false; // Create our DSound buffer (or rather, the wrapper around it) fDSoundBuffer = new plDSoundBuffer( bufferSize, header, is3D, IsPropertySet( kPropLooping ), tryStatic ); if( !fDSoundBuffer->IsValid() ) { plString str = plFormat("Can't create sound buffer for {}.wav. This could happen if the wav file is a stereo file." " Stereo files are not supported on 3D sounds. If the file is not stereo then please report this error.", GetFileName()); IPrintDbgMessage(str.c_str(), true); fFailed = true; delete fDSoundBuffer; fDSoundBuffer = nil; return false; } plProfile_BeginTiming( StaticSndShoveTime ); if(!fDSoundBuffer->FillBuffer(buffer->GetData(), buffer->GetDataLength(), &header)) { delete fDSoundBuffer; fDSoundBuffer = nil; plStatusLog::AddLineS("audio.log", "Could not play static sound, no voices left %s", GetKeyName().c_str()); return false; } plProfile_EndTiming( StaticSndShoveTime ); IRefreshEAXSettings( true ); fTotalBytes = bufferSize; plProfile_NewMem(MemSounds, fTotalBytes); // get pertinent info float length = (float)bufferSize / (float)header.fAvgBytesPerSec; SetLength(length); if( fLoadFromDiskOnDemand && !IsPropertySet( kPropLoadOnlyOnCall ) ) FreeSoundData(); return true; } return false; }
hsBool plWin32GroupedSound::LoadSound( hsBool is3D ) { if( fFailed ) return false; if( fPriority > plgAudioSys::GetPriorityCutoff() ) return false; // Don't set the failed flag, just return if( !plgAudioSys::Active() || fDSoundBuffer != nil ) return false; // Debug flag #1 if( fChannelSelect > 0 && plgAudioSys::IsDebugFlagSet( plgAudioSys::kDisableRightSelect ) ) { // Force a fail fFailed = true; return false; } // We need it to be resident to read in plSoundBuffer::ELoadReturnVal retVal = IPreLoadBuffer(true); plSoundBuffer *buffer = (plSoundBuffer *)fDataBufferKey->ObjectIsLoaded(); if(!buffer) { return plSoundBuffer::kError; } if( retVal == plSoundBuffer::kPending) // we are still reading data. { return true; } // We need it to be resident to read in if( retVal == plSoundBuffer::kError) { plString str = plString::Format("Unable to open .wav file %s", fDataBufferKey ? fDataBufferKey->GetName().c_str() : "nil"); IPrintDbgMessage( str.c_str(), true ); fFailed = true; return false; } SetProperty( kPropIs3DSound, is3D ); plWAVHeader header = buffer->GetHeader(); // Debug flag #2 if( fChannelSelect == 0 && header.fNumChannels > 1 && plgAudioSys::IsDebugFlagSet( plgAudioSys::kDisableLeftSelect ) ) { // Force a fail fFailed = true; return false; } // Calculate the maximum size for our buffer. This will be the length of the longest sound we're going to // have to play. uint16_t i; uint32_t maxSoundSize, len; for( i = 1, maxSoundSize = 0; i < fStartPositions.GetCount(); i++ ) { len = fStartPositions[ i ] - fStartPositions[ i - 1 ]; if( len > maxSoundSize ) maxSoundSize = len; } len = buffer->GetDataLength() - fStartPositions[ fStartPositions.GetCount() - 1 ]; if( len > maxSoundSize ) maxSoundSize = len; // Based on that, allocate our buffer uint32_t bufferSize = maxSoundSize - ( maxSoundSize % header.fBlockAlign ); if( header.fNumChannels > 1 && is3D ) { // We can only do a single channel of 3D sound. So copy over one (later) bufferSize /= header.fNumChannels; header.fBlockAlign /= header.fNumChannels; header.fAvgBytesPerSec /= header.fNumChannels; header.fNumChannels = 1; } fNumDestChannels = (uint8_t)(header.fNumChannels); fNumDestBytesPerSample = (uint8_t)(header.fBlockAlign); // Create our DSound buffer (or rather, the wrapper around it) fDSoundBuffer = new plDSoundBuffer( bufferSize, header, is3D, IsPropertySet( kPropLooping ), true ); if( !fDSoundBuffer->IsValid() ) { char str[256]; sprintf(str, "Can't create sound buffer for %s.wav. This could happen if the wav file is a stereo file. Stereo files are not supported on 3D sounds. If the file is not stereo then please report this error.", GetFileName()); IPrintDbgMessage( str, true ); fFailed = true; delete fDSoundBuffer; fDSoundBuffer = nil; return false; } IRefreshEAXSettings( true ); // Fill the buffer with whatever our current sound is. IFillCurrentSound( 0 ); // Logging plString str = plString::Format(" Grouped %s %s allocated (%d msec).", buffer->GetFileName() != nil ? "file" : "buffer", buffer->GetFileName() != nil ? buffer->GetFileName() : buffer->GetKey()->GetUoid().GetObjectName().c_str(), //fDSoundBuffer->IsHardwareAccelerated() ? "hardware" : "software", //fDSoundBuffer->IsStaticVoice() ? "static" : "dynamic", #ifdef PL_PROFILE_ENABLED gProfileVarStaticSndShoveTime.GetValue() ); #else 0 ); #endif IPrintDbgMessage( str.c_str() ); if( GetKey() != nil && GetKeyName().Find( "Footstep" ) >= 0 ) ; else plStatusLog::AddLineS( "audioTimes.log", "%s (%s)", str.c_str(), GetKey() ? GetKeyName().c_str() : "unkeyed" ); fTotalBytes = bufferSize; plProfile_NewMem( MemSounds, fTotalBytes ); // All done! // if( fLoadFromDiskOnDemand ) // IUnloadDataBuffer(); FreeSoundData(); return true; }
////////////////////////////////////////////////////////////// // Override, 'cause we don't want to actually LOAD the sound for streaming, // just make sure it's decompressed and such and ready to stream. plSoundBuffer::ELoadReturnVal plWin32StreamingSound::IPreLoadBuffer( bool playWhenLoaded, bool isIncidental /* = false */ ) { if(fPlayWhenStopped) return plSoundBuffer::kPending; bool sfxPath = fNewFilename.IsValid() ? false : true; if (fDataStream != nil && !fNewFilename.IsValid()) return plSoundBuffer::kSuccess; // Already loaded if(!ILoadDataBuffer()) { return plSoundBuffer::kError; } plSoundBuffer *buffer = (plSoundBuffer *)fDataBufferKey->ObjectIsLoaded(); if(!buffer) return plSoundBuffer::kError; // The databuffer also needs to know if the source is compressed or not if (fNewFilename.IsValid()) { buffer->SetFileName(fNewFilename); buffer->SetFlag(plSoundBuffer::kStreamCompressed, fIsCompressed); fNewFilename = ""; if(fReallyPlaying) { fPlayWhenStopped = true; return plSoundBuffer::kPending; } } if( buffer->IsValid() ) { plAudioFileReader::StreamType type = plAudioFileReader::kStreamNative; fStreamType = kStreamCompressed; if(!buffer->HasFlag(plSoundBuffer::kStreamCompressed)) { if(buffer->GetDataLengthInSecs() > plgAudioSys::GetStreamFromRAMCutoff( )) { fStreamType = kStreamFromDisk; type = plAudioFileReader::kStreamWAV; } else { fStreamType = kStreamFromRAM; type = plAudioFileReader::kStreamRAM; } } if(!fStartPos) { if(buffer->AsyncLoad(type, isIncidental ? 0 : STREAMING_BUFFERS * STREAM_BUFFER_SIZE ) == plSoundBuffer::kPending) { fPlayWhenLoaded = playWhenLoaded; fLoading = true; return plSoundBuffer::kPending; } } fSrcFilename = buffer->GetFileName(); bool streamCompressed = (buffer->HasFlag(plSoundBuffer::kStreamCompressed) != 0); delete fDataStream; fDataStream = buffer->GetAudioReader(); if(!fDataStream) { plAudioCore::ChannelSelect select = buffer->GetReaderSelect(); bool streamCompressed = (buffer->HasFlag(plSoundBuffer::kStreamCompressed) != 0); /// Open da file plFileName strPath = plFileSystem::GetCWD(); if (sfxPath) strPath = plFileName::Join(strPath, "sfx"); strPath = plFileName::Join(strPath, fSrcFilename); fDataStream = plAudioFileReader::CreateReader(strPath, select,type); } if( fDataStream == nil || !fDataStream->IsValid() ) { delete fDataStream; fDataStream = nil; return plSoundBuffer::kError; } IPrintDbgMessage(plString::Format(" Readied file %s for streaming", fSrcFilename.AsString().c_str()).c_str()); // dont free sound data until we have a chance to use it in load sound return fDataStream ? plSoundBuffer::kSuccess : plSoundBuffer::kError; } plStatusLog::AddLineS("audio.log", "EnsureLoadable failed for streaming sound %d", fDataBufferKey->GetName().c_str()); return plSoundBuffer::kError; }
bool plWin32StreamingSound::LoadSound( bool is3D ) { if( fFailed ) return false; if( !plgAudioSys::Active() || fDSoundBuffer ) return false; if( fPriority > plgAudioSys::GetPriorityCutoff() ) return false; // Don't set the failed flag, just return // Debug flag #1 if( is3D && fChannelSelect > 0 && plgAudioSys::IsDebugFlagSet( plgAudioSys::kDisableRightSelect ) ) { // Force a fail fFailed = true; return false; } plSoundBuffer::ELoadReturnVal retVal = IPreLoadBuffer(true); if(retVal == plSoundBuffer::kPending) return true; if( retVal == plSoundBuffer::kError ) { plString str = plString::Format( "Unable to open streaming source %s", fDataBufferKey->GetName().c_str() ); IPrintDbgMessage( str.c_str(), true ); fFailed = true; return false; } SetProperty( kPropIs3DSound, is3D ); plWAVHeader header = fDataStream->GetHeader(); uint32_t bufferSize = (uint32_t)(fBufferLengthInSecs * header.fAvgBytesPerSec); // Debug flag #2 if( is3D && fChannelSelect == 0 && header.fNumChannels > 1 && plgAudioSys::IsDebugFlagSet( plgAudioSys::kDisableLeftSelect ) ) { // Force a fail fFailed = true; return false; } if( header.fNumChannels > 1 && is3D ) { // We can only do a single channel of 3D sound. So copy over one (later) bufferSize /= header.fNumChannels; header.fBlockAlign /= header.fNumChannels; header.fAvgBytesPerSec /= header.fNumChannels; header.fNumChannels = 1; } // Actually create the buffer now (always looping) fDSoundBuffer = new plDSoundBuffer( bufferSize, header, is3D, IsPropertySet(kPropLooping), false, true ); if( !fDSoundBuffer->IsValid() ) { fDataStream->Close(); delete fDataStream; fDataStream = nil; delete fDSoundBuffer; fDSoundBuffer = nil; plString str = plString::Format("Can't create sound buffer for %s.wav. This could happen if the wav file is a stereo file." " Stereo files are not supported on 3D sounds. If the file is not stereo then please report this error.", GetFileName().AsString().c_str()); IPrintDbgMessage(str.c_str(), true); fFailed = true; return false; } fTotalBytes = (uint32_t)bufferSize; plProfile_NewMem(MemSounds, fTotalBytes); plSoundBuffer *buffer = (plSoundBuffer *)fDataBufferKey->ObjectIsLoaded(); if(!buffer) return false; bool setupSource = true; if(!buffer->GetData() || fStartPos) { if(fStartPos && fStartPos <= fDataStream->NumBytesLeft()) { fDataStream->SetPosition(fStartPos); plStatusLog::AddLineS("syncaudio.log", "startpos %d", fStartPos); } // if we get here we are not starting from the beginning of the sound. We still have an audio loaded and need to pick up where we left off if(!fDSoundBuffer->SetupStreamingSource(fDataStream)) { setupSource = false; } } else { // this sound is starting from the beginning. Get the data and start it. if(!fDSoundBuffer->SetupStreamingSource(buffer->GetData(), buffer->GetAsyncLoadLength())) { setupSource = false; } } if(!setupSource) { fDataStream->Close(); delete fDataStream; fDataStream = nil; delete fDSoundBuffer; fDSoundBuffer = nil; plStatusLog::AddLineS("audio.log", "Could not play streaming sound, no voices left %s", GetKeyName().c_str()); return false; } FreeSoundData(); IRefreshEAXSettings( true ); // Debug info char str[ 256 ]; snprintf( str, arrsize(str), " Streaming %s.", fSrcFilename.AsString().c_str() ); IPrintDbgMessage( str ); plStatusLog::AddLineS( "audioTimes.log", 0xffffffff, "Streaming %4.2f secs of %s", fDataStream->GetLengthInSecs(), GetKey()->GetUoid().GetObjectName().c_str() ); // Get pertinent info SetLength( (float)fDataStream->GetLengthInSecs() ); // Set up our deswizzler, if necessary delete fDeswizzler; if( fDataStream->GetHeader().fNumChannels != header.fNumChannels ) fDeswizzler = new plSoundDeswizzler( (uint32_t)(fBufferLengthInSecs * fDataStream->GetHeader().fAvgBytesPerSec), (uint8_t)(fDataStream->GetHeader().fNumChannels), header.fBitsPerSample / 8 ); else fDeswizzler = nil; // LEAVE THE WAV FILE OPEN! (We *are* streaming, after all :) return true; }
////////////////////////////////////////////////////////////// // Override, 'cause we don't want to actually LOAD the sound for streaming, // just make sure it's decompressed and such and ready to stream. plSoundBuffer::ELoadReturnVal plWin32StreamingSound::IPreLoadBuffer( hsBool playWhenLoaded, hsBool isIncidental /* = false */ ) { if(fPlayWhenStopped) return plSoundBuffer::kPending; hsBool sfxPath = fNewFilename.size() ? false : true; if( fDataStream != nil && fNewFilename.size() == 0) return plSoundBuffer::kSuccess; // Already loaded if(!ILoadDataBuffer()) { return plSoundBuffer::kError; } plSoundBuffer *buffer = (plSoundBuffer *)fDataBufferKey->ObjectIsLoaded(); if(!buffer) return plSoundBuffer::kError; // The databuffer also needs to know if the source is compressed or not if(fNewFilename.length()) { buffer->SetFileName(fNewFilename.c_str()); buffer->SetFlag(plSoundBuffer::kStreamCompressed, fIsCompressed); fNewFilename.clear(); if(fReallyPlaying) { fPlayWhenStopped = true; return plSoundBuffer::kPending; } } if( buffer->IsValid() ) { plAudioFileReader::StreamType type = plAudioFileReader::kStreamNative; fStreamType = kStreamCompressed; if(!buffer->HasFlag(plSoundBuffer::kStreamCompressed)) { if(buffer->GetDataLengthInSecs() > plgAudioSys::GetStreamFromRAMCutoff( )) { fStreamType = kStreamFromDisk; type = plAudioFileReader::kStreamWAV; } else { fStreamType = kStreamFromRAM; type = plAudioFileReader::kStreamRAM; } } if(!fStartPos) { if(buffer->AsyncLoad(type, isIncidental ? 0 : STREAMING_BUFFERS * STREAM_BUFFER_SIZE ) == plSoundBuffer::kPending) { fPlayWhenLoaded = playWhenLoaded; fLoading = true; return plSoundBuffer::kPending; } } char str[ 256 ]; strncpy( fSrcFilename, buffer->GetFileName(), sizeof( fSrcFilename ) ); bool streamCompressed = (buffer->HasFlag(plSoundBuffer::kStreamCompressed) != 0); delete fDataStream; fDataStream = buffer->GetAudioReader(); if(!fDataStream) { plAudioCore::ChannelSelect select = buffer->GetReaderSelect(); bool streamCompressed = (buffer->HasFlag(plSoundBuffer::kStreamCompressed) != 0); /// Open da file char strPath[ kFolderIterator_MaxPath ]; getcwd(strPath, kFolderIterator_MaxPath); if(sfxPath) strcat( strPath, "\\sfx\\" ); else { // if we've changing the filename don't append 'sfx', just append a '\' since a path to the folder is expected strcat( strPath, "\\"); } strcat( strPath, fSrcFilename ); fDataStream = plAudioFileReader::CreateReader(strPath, select,type); } if( fDataStream == nil || !fDataStream->IsValid() ) { delete fDataStream; fDataStream = nil; return plSoundBuffer::kError; } sprintf( str, " Readied file %s for streaming", fSrcFilename ); IPrintDbgMessage( str ); // dont free sound data until we have a chance to use it in load sound return fDataStream ? plSoundBuffer::kSuccess : plSoundBuffer::kError; } plStatusLog::AddLineS("audio.log", "EnsureLoadable failed for streaming sound %d", fDataBufferKey->GetName().c_str()); return plSoundBuffer::kError; }