1

EDIT: I did not pass the appropriate flags into the initialize method, I think the Audio Sessions page on MSDN is slightly misleading in this regard as it seems to suggest it is default behavior, however the default behavior is that sessions are associated with the process, to allow them to terminate when a stream is released you need to pass:

AUDCLNT_SESSIONFLAGS_EXPIREWHENUNOWNED AUDCLNT_SESSIONFLAGS_DISPLAY_HIDEWHENEXPIRED

http://msdn.microsoft.com/en-us/library/windows/desktop/dd370789(v=vs.85).aspx


Ok so I've been trying to get some audio working, essentially I want to have multiple windows open under the same process playing audio and video (audio is muted on all but topmost). I am having a problem when it comes to audio sessions, I create a unique session for each stream however the session doesn't close when I thought I closed down the stream.

My understanding is that sndvol will display sessions in active / inactive states and when you release all references to streams the session will set to expired and no longer appear in sndvol, however I find that for every stream I open a new session appears in sndvol but it won't be removed until the whole process ends, rather than when the audio thread ends (ie when I close a window / change inputs).

Here is my audio thread, I've stripped it down to its bare bones and the IAudioSessionControl interface is just used to help me figure out the state of the session to debug, in the 'audio loop' it is active, everywhere else inactive, however I thought it would expire after I release pAudioClient am I wrong here, what else should I be releasing?

WORD WINAPI
AudioThread (
   LPVOID   lpThreadParameter )
{
   HRESULT              hr;
   PAUDIOPARMS          pAudioParms = (PAUDIOPARMS)lpThreadParameter;
   IMMDeviceEnumerator  *pEnumerator = NULL;
   IMMDevice            *pDevice = NULL;
   IAudioClient         *pAudioClient = NULL;
   IAudioSessionControl *pAudioSessionControl;
   AudioSessionState    audioSessionState;
   GUID                 sessionGUID;
   WAVEFORMATEXTENSIBLE *pwfx = NULL;

   /* Initialise WASAPI interfaces and find audio endpoint. */
   hr = CoCreateInstance ( &CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, 
         &IID_IMMDeviceEnumerator, (void**)&pEnumerator);
   EXIT_ON_ERROR(hr)

   hr = pEnumerator->lpVtbl->GetDefaultAudioEndpoint(pEnumerator, eRender, 
         eConsole, &pDevice);
   EXIT_ON_ERROR(hr)
   SAFE_RELEASE ( pEnumerator );

   hr = pDevice->lpVtbl->Activate(pDevice, &IID_IAudioClient, CLSCTX_ALL,
         NULL, (void**)&pAudioClient);
   EXIT_ON_ERROR(hr)
   SAFE_RELEASE ( pDevice );


   hr = pAudioClient->lpVtbl->GetMixFormat(pAudioClient,&pwfx);
   CoCreateGuid ( &sessionGUID );
   hr = pAudioClient->lpVtbl->Initialize ( pAudioClient, AUDCLNT_SHAREMODE_SHARED,
            0, 853333,  0,  pwfx, &sessionGUID );
   if ( pwfx )
      CoTaskMemFree ( pwfx );

   hr = pAudioClient->lpVtbl->GetService ( pAudioClient, &IID_IAudioSessionControl, (void**)&pAudioSessionControl );
   pAudioSessionControl->lpVtbl->GetState ( pAudioSessionControl, &audioSessionState );
   hr = pAudioClient->lpVtbl->Start(pAudioClient);
   EXIT_ON_ERROR(hr)

   /* Allow OpenSharedAudio thread to continue. */
   SetEvent ( pAudioParms->HStartEvent );

   while (!pAudioParms->BClose)
   {
      /* Audio Loop. */
      pAudioSessionControl->lpVtbl->GetState ( pAudioSessionControl, &audioSessionState );
   }
   hr = pAudioClient->lpVtbl->Stop(pAudioClient);
   EXIT_ON_ERROR(hr)

   Exit:

   SAFE_RELEASE ( pAudioClient );
   pAudioParms->Error = hr;

   pAudioSessionControl->lpVtbl->GetState ( pAudioSessionControl, &audioSessionState );
   SAFE_RELEASE ( pAudioSessionControl );
   /* Allow OpenSharedAudio thread to continue. */
   SetEvent ( pAudioParms->HStartEvent );
   return 0;
}

I have SAFE_RELEASE() defined as follows:

#define SAFE_RELEASE(pUnk)  \
              if ((pUnk) != NULL)  \
                { (pUnk)->lpVtbl->Release(pUnk); (pUnk) = NULL; }
Adwo
  • 171
  • 1
  • 10
  • Maybe you could put all the release on exit, in creation reverse order: AddRef enumerator, AddRef device ... Exit: Release Device, Release enumerator. – Simon Mourier Jun 12 '13 at 15:20
  • Thanks for the tip, unfortunately it hasn't solved the problem. I'll keep bashing at it until I figure out what I'm doing wrong. – Adwo Jun 14 '13 at 10:12
  • You are not doing `CoInitialize`, though this is not the cause of the problem in question. Maybe you can `Reset` your client when you're done to force the session to close. – Roman R. Jun 18 '13 at 17:37
  • ["After a session has been inactive **for a period of time**, the system changes the state of the session from inactive to expired."](http://msdn.microsoft.com/en-us/library/windows/desktop/dd370796%28v=vs.85%29.aspx) - there is no promise session is gone immediately. – Roman R. Jun 18 '13 at 17:39
  • 2
    The audio sessions explanation is slightly misleading, I needed to pass a flag into initialize to allow sessions to expire, otherwise they associate with the process and terminate with it. http://msdn.microsoft.com/en-us/library/windows/desktop/dd370789(v=vs.85).aspx Thanks for the help everyone :) – Adwo Jun 25 '13 at 12:07
  • I've added the flags, but noticed the app won't be removed from SndVol until after I close SndVol and re-open. This is super strange behavior... It could be something wrong on my end but I can't imagine what it would be. – Rick Oct 13 '22 at 17:42

0 Answers0