0

現在、プロジェクトのサウンド システムを作成しています。PlayAsync を呼び出すたびに、std::thread コールバックでサウンドのインスタンスが作成されます。このコールバックではサウンドデータが周期的に進んでいきます。スレッドが進むと、サウンド インスタンスが静的ベクターに格納されます。スレッドが終了すると (サウンドが完了する)、サウンド インスタンスが削除され、インスタンス カウントが減少します。アプリケーションが終了すると、すべてのサウンドを即座に停止し、サウンドのすべてのサイクルに割り込みを送信する必要があります。

問題は、これらのサウンドを保持する配列にあります。よくわかりませんが、この目的にはベクトルは適切な選択ではないと思います..コードは次のとおりです。

void gSound::PlayAsync()
{
    std::thread t(gSound::Play,mp_Audio,std::ref(*this));
    t.detach();
}
    HRESULT gSound::Play(IXAudio2* s_XAudio,gSound& sound)
{                
    gSound* pSound = new gSound(sound);   
    pSound->m_Disposed = false;         

    HRESULT hr;      
    // Create the source voice
    IXAudio2SourceVoice* pSourceVoice;
    if( FAILED( hr = s_XAudio->CreateSourceVoice( &pSourceVoice, pSound->pwfx ) ) )
    {
        gDebug::ShowMessage(L"Error creating source voice");      
        return hr;
    }

    // Submit the wave sample data using an XAUDIO2_BUFFER structure
    XAUDIO2_BUFFER buffer = {0};
    buffer.pAudioData = pSound->pbWaveData;
    buffer.Flags = XAUDIO2_END_OF_STREAM;  // tell the source voice not to expect any data after this buffer
    buffer.AudioBytes = pSound->cbWaveSize;

    if( FAILED( hr = pSourceVoice->SubmitSourceBuffer( &buffer ) ) )
    {
        gDebug::ShowMessage(L"Error submitting source buffer");
        pSourceVoice->DestroyVoice();   
        return hr;
    }

    hr = pSourceVoice->Start( 0 );     

    // Let the sound play
    BOOL isRunning = TRUE;
    m_soundInstanceCount++;     
    mp_SoundInstances.push_back(pSound); #MARK2
    while( SUCCEEDED( hr ) && isRunning && pSourceVoice != nullptr && !pSound->m_Interrupted)
    {    
        XAUDIO2_VOICE_STATE state;
        pSourceVoice->GetState( &state );
        isRunning = ( state.BuffersQueued > 0 ) != 0;     
        Sleep(10);
    }   
    pSourceVoice->DestroyVoice();   
    delete pSound;pSound = nullptr; //its correct ??
    m_soundInstanceCount--; 
    return 0;    
}

void gSound::InterrupAllSoundInstances()
{
    for(auto Iter = mp_SoundInstances.begin(); Iter != mp_SoundInstances.end(); Iter++)
    {
        if(*Iter != nullptr)//#MARK1
        {
        (*Iter)->m_Interrupted = true;
        }
    }
}

そして、これはサウンド オブジェクトを破棄する前にアプリケーション クラスで呼び出します。メイン アプリケーションがすぐにループした後です。

    gSound::InterrupAllSoundInstances();
while (gSound::m_soundInstanceCount>0)//waiting for deleting all sound instances in threads
{

}

質問:

だから #MARK1 - ベクトルでメモリ検証をチェックする方法は? 私はそれについて経験がありません。無効なメモリをチェックしようとするとエラーが発生します(nullに等しくない)

#MARK2 - ベクターの正しい使い方は?それともベクトルは悪い選択ですか?サウンド インスタンスを作成するたびに、サイズが大きくなります。良くない。

4

1 に答える 1

1

典型的な問題:

delete pSound;
pSound = nullptr; // issue

これはあなたが思うことをしません。

事実上pSoundnull に設定されますが、同じポインターの他のコピー (ベクター内に少なくとも 1 つ) もあり、それらは null 化されません。これが、 に が見つからない理由nullptrですvector

代わりに、インデックスをベクトルに登録し、それを無効にすることができます: mp_SoundInstances[index] = nullptr;.

しかし、あなたは単にメモリ処理をよく理解しておらず、構造を欠いているのではないかと心配しています。メモリ処理については、詳細がないとわかりにくく、システムが複雑すぎて説明が長すぎるのではないかと心配しています。構造については、Observerパターンについて少し読む必要があります。

于 2012-06-03T14:43:36.180 に答える