Audio help needed

    This site uses cookies. By continuing to browse this site, you are agreeing to our Cookie Policy.

    • Audio help needed

      In my Initialize method before entering the main loop I am starting to play background music in a separate thread. I did this because I was unable to start the music and continue on with execution of the program. The current song is just a converted mp3 -> wav (about 4 minutes long). How can I tell the song to stop playing and the thread to termintate when the user clicks the Exit button or if the user clicks start and I want to change the background music.

      FYI. I am using XAudio2 as my music API.
    • RE: Audio help needed

      Well - you could encapsulate the background music in a manager class that contains the thread. When you want to change the music - you should just set a member variable in the manager class that is read by the thread.

      If the member variable is set to a music file name or something, the thread can easilly detect a change in it and do whatever you need.

      One thing though - you should have the thread synchronise access to that member variable - a thread can read it at any time and you don't want it to read it at exactly the same time it is being changed.

      You'll need to use a syncronization method such as a mutex to do this.
      Mr.Mike
      Author, Programmer, Brewer, Patriot
    • RE: Audio help needed

      Thanks for the quick reply. I have a SoundManager that owns the thread and starts it. If the thread is off playing a song, how can it check the variable and know that it should stop? Or is it that the SoundManager should check the variable and then tell the thread to stop if it detects an event to do so?

      Thanks
    • RE: Audio help needed

      The majority of the time a thread should never be told to stop explicitly (ex. via StopThread, etc.) and should be in control of killing its own execution except in cases where it refuses to stop for whatever reason.

      Personally I would take the route of having stopping/changing the song be a two step process to avoid having to lock a mutex each and every time you check the name.

      While you should review articles on lockless threaded design, the key here is to make sure to perform atomic operations whenever possible since the instruction can be carried out by the CPU in a single cycle (16-bit alignment that Mike discusses in GCC is extremely important here). As an example:

      Source Code

      1. ThreadFunc( void* pParam )
      2. {
      3. // you can check this without locking since the
      4. // operation should typically be atomic
      5. while( bKeepPlaying )
      6. {
      7. // keep doing whatever you want to do here
      8. // check a boolean to see if the song has been
      9. // changed, if so then you know to lock
      10. if( bSongChanged )
      11. {
      12. // I won't get into memory fences, so sync
      13. // using a mutex (user -> kernel mode on
      14. // Windows is a slow operation)
      15. LockMutex( hMutex )
      16. DoSongLoadingHere( "title_of_song" )
      17. UnlockMutex( hMutex )
      18. }
      19. }
      Display All


      I believe this is something similar to what Mike was suggesting and your question really comes down to the design of your sound manager. If the thread is executing on a class method you can simply check member variables; however if its running on a standalone function you will need to use global variables to control stopping and some changing. To be safe, look into the C++ "volatile" keyword which indicates the value may be referenced by two seperate processes (or threads) at the "same" time.
    • RE: Audio help needed

      Hey don't you have to put a lock around the check for the changed song? This variable is going to be changed outside the thread, right? That should be synchronized....I think.
      Mr.Mike
      Author, Programmer, Brewer, Patriot
    • RE: Audio help needed

      I guess my question boils down to if I am playing a song in the thread, how can the thread also be checking a variable if the song playing is in the only execution path of the thread? Is there a way to have the thread play the song in the background and still allow the thread to do other tasks like check variables?
    • RE: Audio help needed

      Here is my code for the SoundManger (where relevant), hope this helps


      static DWORD WINAPI ThreadStart(LPVOID info)
      {
      return static_cast<SoundManager*>(info)->Play();
      }

      void SoundManager::Start()
      {
      m_hThread = CreateThread(
      NULL, 0, &SoundManager::ThreadStart, this, 0, NULL);
      }

      bool SoundManager::Play()
      {
      HRESULT hr;
      if (FAILED(hr = PlayPCM(pXAudio2, "2.wav")))
      {
      MessageBox(NULL, "Error while playing PCM", "Playing Error", MB_OK);
      return false;
      }

      pMasteringVoice->DestroyVoice();
      SAFE_RELEASE( pXAudio2 );
      CoUninitialize();
      return true;
      }
    • Mike,

      Woops you are correct. Without a memory fence and forced read/write ordering boundaries (both for the compiler and inline ASM instruction(s) for the CPU) the check on the boolean will require a lock also.

      I've become accustomed to avoiding mutexes whenever possible so my example was a mix of wha I typically do (ie. forced read/write ordering) while trying to illustrate what I thought you were proposing, good catch :).

      Sosa,

      While I have not worked with XAudio, based on what I can find on the MSDN, I believe you want to use an XAudio2 callback in this case (or a hybrid of one) to sit between your sound manager, and the sample that is currently playing via your call to PlayPCM. The following link explains XAudio2 callbacks:

      msdn.microsoft.com/en-us/library/cc677012(VS.85).aspx

      I believe with your current implementation you don't have a simple way to accomplish what you are trying to as the thread is simply waiting on the PlayPCM call to return before killing its execution.

      Hopefully the above link helps, and if you go back one page (msdn.microsoft.com/en-us/library/bb694505(VS.85).aspx) and look at voice callbacks, it mentions how sounds can be handled asynchronously via the voice callback mechanisms as well.

      The post was edited 1 time, last by Permafried- ().