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;

}
Beispiel #2
0
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;
}
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;
}