Thread: Muting other applications, then playing a sound

  1. #1
    Registered User
    Join Date
    Sep 2010
    Posts
    2

    Question Muting other applications, then playing a sound

    Hi,

    I'm trying to find a way to mute all sounds currently playing, and play a WAV or MP3. So far I've tried DirectSound to no avail.

    Any ideas?

  2. #2
    Registered User C_ntua's Avatar
    Join Date
    Jun 2008
    Posts
    1,853
    I don't think you can mute them, but maybe you can stop them and then resume them.
    Maybe getting the primary buffer, stopping it, starting a secondary buffer and then starting the primary again? Maybe just stopping the buffer, creating another one and playing it, resuming it?

    I don't remember if you can get a sound being played or not.

  3. #3
    Registered User
    Join Date
    Sep 2010
    Posts
    2
    The problem with DirectSound is once I use WritePrimary and the Primary Buffer, there is no way to use Secondary Buffers. And I could find no documentation or examples on handling the Primary Buffer to play files.

  4. #4
    Registered User C_ntua's Avatar
    Join Date
    Jun 2008
    Posts
    1,853
    Dunno unfortunately a way or if it is even possible.
    You can try SlimDX Homepage which is based on DirectSound, but maybe you can find examples and documentation there.

    Maybe you can give more information for people to find a work around since a general solution might not be available.

  5. #5
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    You would set the volume level of the currently playing buffer to zero or infinity. Since the primary buffer is the only playing buffer I would imagine you would set that to zero. The primary buffer is essentially like the 'Master' on a sound board. The secondary buffers can be thought of as 'Channels' on a sound board. Each secondary buffer can have volume but those volumes will never exceed the final primary buffer volume. The primary buffer, if memory serves me, is handled by DirectSound. The user handles the secondary buffers.

    I stopped using DirectSound and moved to OpenAL. I'm not sure there is a C# wrapper for OpenAL but you could easily write one using C++/CLI and interface that with OpenAL. You can make use of the msclr namespace and use auto_gcroot or gcroot to enable un-managed classes to use managed objects (pointers into the managed heap as Microsoft puts it). This allows C++ objects to call into .NET managed objects.

    C++ OpenALWrapper.dll - links with OpenAL
    Code:
    #ifdef _MANAGED
    public
    #endif
    class OpenALWrapper
    {
         public:
            OpenALWrapper(unsigned int numSources)
            {
                  // Init OpenAL here
            }
    
            bool AddSound(const char *pSoundName,const char *pFilename)
            {
                   // Add sound here and return result
            }
            ...
            ...
    };
    C++/CLI OpenALBridge.dll - links with OpenALWrapper.dll
    Code:
    #include "OpenALWrapper.h"
    using namespace System::Runtime::InteropServices;
    
    public ref class OpenALBridge
    {
        public:
            OpenALBridge(unsigned int numSources)
            {
                  m_pUMOpenAL = new OpenALWrapper(numSources);
            }
    
            virtual ~OpenALBridge()
            {
                 if (m_pUMOpenAL)
                 {
                     delete m_pUMOpenAL;
                     m_pUMOpenAL = 0;
                 }
            }             
    
            bool AddSound(System::String ^soundName,System::String ^filename)
            {
                  bool result = false;
    
                  // Convert System::String to const char *
                  const char *pSoundName = ConvertToCString(soundName);
                  const char *pFileName = ConvertToCString(fileName);
    
                  // Call into C++ OpenALWrapper
                  result =  m_pUMOpenAL->AddSound(pSoundName,pFileName);
    
                  // Cleanup memory allocated in string conversion
                  CleanupCString(pSoundName);
                  CleanupCString(pFileName);
    
                  return result;
            }
    
            bool RemoveSound(System::String ^soundName);
            ManagedSoundSample ^GetSound(System::String ^soundName);
            bool PlaySound(System::String ^soundName);
            ...
    
        private:
            OpenALWrapper *m_pUMOpenAL;
    };
    
    const char * ConvertToCString(System::String ^managedString)
    {
       return (const char*)(Marshal::StringToHGlobalAnsi(managedString)).ToPointer();
    }
    
    void CleanupCString(IntPtr string)
    {
        Marshall.FreeHGlobal(string);
    }
    C# - has a reference to OpenALBridge.dll
    Code:
    public class Foo
    {
        public ManagedOpenAL { get; private set; }
    
        public Foo(unsigned int numSources)
        {
            ManagedOpenAL = new OpenALBridge(numSources);
            ...
        }
    
       public bool AddSound(string soundName,string fileName)
       {
           bool result = false;
           if (ManagedOpenAL != null)
          {
             result = ManagedOpenAL.AddSound(soundName,fileName);
          }
          return result;
        }           
        ...
    }
    Here is an MSDN link to explain the string conversion routines. StringToHGlobalAnsi allocates a block of memory that must be cleaned up. Note that if you wanted to convert to std::string you could but since you would be calling into a C++ DLL I would recommend the DLL use POD types at the boundary.
    Marshal.StringToHGlobalAnsi Method (System.Runtime.InteropServices)

    Keep in mind this is a SAMPLE. I did not compile this and I'm sure the IntPtr and const char * are going to give some warnings in the C functions. Now once all this functionality is correctly wrapped and bridged you can use OpenAL from C# just as any other C# object. Ref classes in C++/CLI are managed classes and are used exactly like any other managed object. This allows you to use OpenAL just as any other C++ app would use it. Because you are using C++/CLI ref classes you don't need any special P/Invoke declarations in C# or mess with data type issues (C++ bool is not C# bool). It is also generally faster to use C++/CLI than the corresponding P/Invoke. I could probably wrap OpenAL in less than a week and if I did not need the extended EAX functionality I could wrap it in about a day. Once you get used to the C++/CLI, C#, and C++ communication and relationships calling into C++ from C# and vice versa becomes very simple to do.

    The order of creation here is:
    C# -> creates the C++/CLI object
    C++/CLI -> creates the C++ object
    C++ -> creates OpenAL

    The call order is:
    C# -> C++/CLI -> C++ -> OpenAL

    You can do: (for say callbacks or listeners)
    OpenAL -> C++ -> C++/CLI -> C#

    But you must use gcroot or auto_gcroot so your unmanaged classes can talk to managed classes.
    Last edited by VirtualAce; 09-20-2010 at 11:16 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Low latency sound effects
    By VirtualAce in forum Game Programming
    Replies: 0
    Last Post: 12-21-2004, 01:58 AM
  2. Updated sound engine code
    By VirtualAce in forum Game Programming
    Replies: 8
    Last Post: 11-18-2004, 12:38 PM
  3. DirectSound - multiple sounds
    By Magos in forum Game Programming
    Replies: 9
    Last Post: 03-03-2004, 04:33 PM
  4. playing sound under water
    By scott27349 in forum Tech Board
    Replies: 9
    Last Post: 01-26-2003, 03:19 PM
  5. sounds?
    By BODYBUILDNERD in forum C++ Programming
    Replies: 6
    Last Post: 12-06-2002, 03:34 PM