Getting Voices to overlap.

Last post 05-01-2008, 8:27 PM by The Luminous Aardvark. 6 replies.
Sort Posts: Previous Next
  •  04-24-2008, 4:04 PM

    Getting Voices to overlap.

    Hi everyone. I am currently trying to get XAudio2 to work in a student game that I am working on. I have been able to get .wav files and streaming files playing but now I have the problem that I cannot get 2 sounds to play overlapping. If I call my play sound function it just queues the sound up and plays it when the one before it has finished. Below is my code
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    void XAudio2Engine::LoadSound(LPCWSTR strFileName)
    {
      HRESULT hr;
      SoundData *TempSound = new SoundData();
      //Find the wav File
      WCHAR strFilePath[MAX_PATH];
      if( FAILED( hr = FindMediaFileCch(strFilePath, MAX_PATH, strFileName)))
        cout << "Couldn't Loacate the wav file\n";
      else
        cout << "Found wav file\n";

      //Open the wav file
      CWaveFile wav;
      if ( FAILED(hr = wav.Open( strFilePath, NULL, WAVEFILE_READ ) ) )
        cout << "Couldn't open the wav file\n";
      else
        cout << "Opened the wav\n";

      // Get format of wave file
      WAVEFORMATEX* pwfx = wav.GetFormat();
      // Calculate how many bytes and samples are in the wave
      DWORD cbWaveSize = wav.GetSize();
      // Read the sample data into memory
      BYTE* pbWaveData = new BYTE[ cbWaveSize ];

      //Read in the wav
      if( FAILED(hr = wav.Read( pbWaveData, cbWaveSize, &cbWaveSize ) ) )
        cout << "Couldn't read the wav\n";
      else
        cout << "wav read\n";

      IXAudio2SourceVoice* pSourceVoice;
      //m_pXAudio->cer
      if( FAILED(hr = m_pXAudio->CreateSourceVoice( &pSourceVoice, pwfx ) ) )
        cout << "Source voice failed\n";
      else
        cout << "Source voice succeded\n";

      TempSound->pSourceVoice = pSourceVoice;
      TempSound->pbWaveData = new BYTE[ cbWaveSize ];
      TempSound->pbWaveData = pbWaveData;
      TempSound->cbWaveSize = cbWaveSize;
      Sounds.push_back(TempSound);

    }

    void XAudio2Engine::PlaySFXSound(int SoundNum)
    {
      HRESULT hr;

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

      if( FAILED(hr = Sounds[SoundNum]->pSourceVoice->SubmitSourceBuffer( &buffer ) ) )
        cout << "Couldn't submit source buffer\n";
      else
        cout << "Source buffer submitted\n";

      //m_pXAudio->
      cout << "PLAY SOUND!!\n";
      hr = Sounds[SoundNum]->pSourceVoice->Start(0);
    }

    And here is how I am playing the sounds
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    MyEngine->LoadSound(L"SillyGoose.wav");
    CDemoThread dmt;

    dmt.Start(0);
    while(true)
    {
    if(GetAsyncKeyState(VK_UP) && UpPressed == false)
    {
    MyEngine->PlaySFXSound(0);
    UpPressed = true;
    }
    if(!GetAsyncKeyState(VK_UP) && UpPressed == true)
    UpPressed = false;
    }
    SleepEx(15 * 1000, FALSE);

    dmt.Stop(true);

    Every time I press up I would like it to play the sound over the previous sound. If anyone is able to give me an idea on how to get this to work it would be greatly appreciated.
  •  04-24-2008, 8:45 PM

    Re: Getting Voices to overlap.

    Hi,

        Sounds to me like you need to create another Source Voice.

    :)

  •  04-28-2008, 2:15 PM

    Re: Getting Voices to overlap.

    Allright so I changed things up a bit and my XAudio2Engine is being linked in by a static libary. Here is my code now.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
      HRESULT hr;
      SoundData *TempSound = new SoundData();
      TempSound->ref = 0;
      //Find the wav File
      WCHAR strFilePath[MAX_PATH];
      if( FAILED( hr = FindMediaFileCch(strFilePath, MAX_PATH, strFileName)))
        return -1;

      //Open the wav file
      CWaveFile wav;
      if ( FAILED(hr = wav.Open( strFilePath, NULL, WAVEFILE_READ ) ) )
        return -1;

      // Get format of wave file
      WAVEFORMATEX* pwfx = wav.GetFormat();
      // Calculate how many bytes and samples are in the wave
      DWORD cbWaveSize = wav.GetSize();
      // Read the sample data into memory
      BYTE* pbWaveData = new BYTE[ cbWaveSize ];

      // Make sure the texture isn't already loaded.
      for (unsigned int i = 0; i < Sounds.size(); i++)
      {
        if(cbWaveSize == SoundsIdea->cbWaveSize && pbWaveData == SoundsIdea->pbWaveData)
        {
          SoundsIdea->ref++;
          return i;
        }
      }

      //Look for an open spot
      int id = -1;
      for(unsigned int i = 0; i < Sounds.size(); ++i)
      {
        if (SoundsIdea->ref == 0)
        {
          id = i;
          break;
        }
      }
      if(id == -1)
      {
        //Read in the wav
        if( FAILED(hr = wav.Read( pbWaveData, cbWaveSize, &cbWaveSize ) ) )
          return -1;

        //IXAudio2SourceVoice* pSourceVoice;
        //if( FAILED(hr = m_pXAudio->CreateSourceVoice( &pSourceVoice, pwfx ) ) )
        //  return -1;

        //TempSound->pSourceVoice = pSourceVoice;
        TempSound->pbWaveData = new BYTE[ cbWaveSize ];
        TempSound->pbWaveData = pbWaveData;
        TempSound->cbWaveSize = cbWaveSize;
        TempSound->ref = 1;
       TempSound->pwfx = wav.GetFormat();

        Sounds.push_back(TempSound);
        return (int)Sounds.size() - 1;
      }
      else
      {
        //Read in the wav
        if( FAILED(hr = wav.Read( pbWaveData, cbWaveSize, &cbWaveSize ) ) )
          return -1;

        //IXAudio2SourceVoice* pSourceVoice;
        //if( FAILED(hr = m_pXAudio->CreateSourceVoice( &pSourceVoice, pwfx ) ) )
        //  return -1;

        //Sounds[id]->pSourceVoice = pSourceVoice;
        Sounds[id]->pbWaveData = pbWaveData;
        Sounds[id]->cbWaveSize = cbWaveSize;
        Sounds[id]->pwfx = wav.GetFormat();
        return id;
      }

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
      HRESULT hr;

      IXAudio2SourceVoice* pSourceVoice;
      SoundData *MySounds = 0;
      if( FAILED(hr = m_pXAudio->CreateSourceVoice( &pSourceVoice, Sounds[SoundNum]->pwfx ) ) )
        cout << "Source voice failed\n";
      else
        cout << "Source voice succeded\n";

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

      if( FAILED(hr = pSourceVoice->SubmitSourceBuffer( &buffer ) ) )
        cout << "Couldn't submit source buffer\n";
      else
        cout << "Source buffer submitted\n";


      cout << "PLAY SOUND!!\n";
      hr = pSourceVoice->Start(0);


    Rather than create a source voice for every sound that I load I now create a source voice in every time I play. The problem that I have now is that doing this causes a crash that I can't track down due to it being linked in I think. All I changed is rather than storing the pSourceVoice in my SoundData i store the WAVEFORMATEX and then create a new source everytime I want a sound to play. Anyone able to see if I am doing somthing wrong?
  •  04-28-2008, 6:36 PM

    Re: Getting Voices to overlap.

    In general, having people read through reams of code to find your problem doesn't get a lot of takers.

    I would suggest putting a breakpoint right where you create the voice. Make sure to inspect all the variable and data structure values after each step, to look for problems. Then step through your program, one line at a time, from that point, until it crashes. You should see which line it crashes on. At that point, you should have a better idea why it crashes.

    If it crashes inside the XAudio code itself, then chances are good that you gave it a bad pointer, or de-allocated a buffer before XAudio was done with the data, or something like that. If you link with the debug version of XAudio, it will check a number of problems for you, and break with an int 3 instruction and some output to the debugger console when you use it wrong (for many possible wrongs, but not all).


    --
    Jon Watte, Direct3D MVP
    kW X-port 3ds Max .X exporter
    14 days after getting my RROD box back, it's going back for service again. Grr.
  •  04-28-2008, 10:46 PM

    Re: Getting Voices to overlap.

    jwatte:
    ... and some output to the debugger console when you use it wrong (for many possible wrongs, but not all).



    Which errors does XAudio2 fail to inform us of?
  •  04-29-2008, 11:49 AM

    Re: Getting Voices to overlap.

    I seem to recall there are cases of wild pointers that won't be caught, for example.


    --
    Jon Watte, Direct3D MVP
    kW X-port 3ds Max .X exporter
    14 days after getting my RROD box back, it's going back for service again. Grr.
  •  05-01-2008, 8:27 PM

    Re: Getting Voices to overlap.

    Hi,

    Not entirely sure about this as a solution but I do have a suggestion.

    The WAVEFORMATEX returned from wav.GetFormat()...

    May I suggest that you allocate a WAVEFORMATEX for Sounds[id]->pwfx and TempSound->pwfx (including any extra bytes) and  copy ( memcpy ) the  wave format returned by wav.GetFormat() including said extra bytes, as I believe that memory is freed in the destructor of the CWaveFile (cannot confirm this as I'm away at the moment).

    Also place a break point in your unmodified code just before CreateSourceVoice and check that the
    Sounds[SoundNum]->pwfx
    is valid. I think you'll find that because it is a pointer to memory that has been freed in the CWaveFile destructor then it is unrelieable.

    Hope this helps.

    :)
View as RSS news feed in XML
©2007 Microsoft Corporation. All rights reserved. Privacy Statement Terms of Use Code of Conduct Feedback