示例#1
0
        /// <summary>
        /// Sets up the hardware resources used by the controller.
        /// </summary>
        private OpenALSoundController()
        {
#if WINDOWS
            // On Windows, set the DLL search path for correct native binaries
            NativeHelper.InitDllDirectory();
#endif

            if (!OpenSoundController())
            {
                throw new NoAudioHardwareException("OpenAL device could not be initialized, see console output for details.");
            }

            if (Alc.IsExtensionPresent(_device, "ALC_EXT_CAPTURE"))
            {
                Microphone.PopulateCaptureDevices();
            }

            // We have hardware here and it is ready

            allSourcesArray = new int[MAX_NUMBER_OF_SOURCES];
            AL.GenSources(allSourcesArray);
            ALHelper.CheckError("Failed to generate sources.");
            Filter = 0;
            if (Efx.IsInitialized)
            {
                Filter = Efx.GenFilter();
            }
            availableSourcesCollection = new List <int>(allSourcesArray);
            inUseSourcesCollection     = new List <int>();
        }
示例#2
0
        /// <summary>
        /// Sets up the hardware resources used by the controller.
        /// </summary>
        private OpenALSoundController()
        {
            if (AL.NativeLibrary == IntPtr.Zero)
            {
                throw new DllNotFoundException("Couldn't initialize OpenAL because the native binaries couldn't be found.");
            }

            if (!OpenSoundController())
            {
                throw new NoAudioHardwareException("OpenAL device could not be initialized, see console output for details.");
            }

            if (Alc.IsExtensionPresent(_device, "ALC_EXT_CAPTURE"))
            {
                Microphone.PopulateCaptureDevices();
            }

            // We have hardware here and it is ready

            allSourcesArray = new int[MAX_NUMBER_OF_SOURCES];
            AL.GenSources(allSourcesArray);
            ALHelper.CheckError("Failed to generate sources.");
            Filter = 0;
            if (Efx.IsInitialized)
            {
                Filter = Efx.GenFilter();
            }
            availableSourcesCollection = new List <int>(allSourcesArray);
            inUseSourcesCollection     = new List <int>();
        }
 public static IEnumerable <string> GetDeviceNames()
 {
     if (!Alc.IsExtensionPresent(IntPtr.Zero, "ALC_ENUMERATION_EXT"))
     {
         return(Enumerable.Empty <string>());
     }
     return(Alc.GetString(IntPtr.Zero, AlcGetStringList.AllDevicesSpecifier));
 }
示例#4
0
        /// <summary>
        /// Checks whether the specified OpenAL extension is supported.
        /// </summary>
        /// <param name="extension">The name of the extension to check (e.g. "ALC_EXT_EFX").</param>
        /// <returns>true if the extension is supported; false otherwise.</returns>
        public bool SupportsExtension(string extension)
        {
            if (disposed)
            {
                throw new ObjectDisposedException(this.GetType().FullName);
            }

            return(Alc.IsExtensionPresent(this.Device, extension));
        }
示例#5
0
        public static string[] AvailableDevices()
        {
            // Returns all devices under Windows Vista and newer
            if (Alc.IsExtensionPresent(IntPtr.Zero, "ALC_ENUMERATE_ALL_EXT"))
            {
                return(QueryDevices("ALC_ENUMERATE_ALL_EXT", AlcGetStringList.AllDevicesSpecifier));
            }

            if (Alc.IsExtensionPresent(IntPtr.Zero, "ALC_ENUMERATION_EXT"))
            {
                return(QueryDevices("ALC_ENUMERATION_EXT", AlcGetStringList.DeviceSpecifier));
            }

            return(new string[] { });
        }
        public AlcDiagnostic(IntPtr dev)
        {
            Trace.WriteLine("--- Alc related errors ---");

            Alc.GetInteger(dev, AlcGetInteger.MajorVersion, 1, out MajorVersion);
            Alc.GetInteger(dev, AlcGetInteger.MinorVersion, 1, out MinorVersion);
            Alc.GetInteger(dev, AlcGetInteger.EfxMajorVersion, 1, out EfxMajorVersion);
            Alc.GetInteger(dev, AlcGetInteger.EfxMinorVersion, 1, out EfxMinorVersion);
            Alc.GetInteger(dev, AlcGetInteger.EfxMaxAuxiliarySends, 1, out EfxMaxAuxiliarySends);

            ExtensionString = Alc.GetString(dev, AlcGetString.Extensions);

            foreach (string s in Alc_Extension_C_Names)
            {
                Extensions.Add(s, Alc.IsExtensionPresent(dev, s));
            }
        }
示例#7
0
        // Loads all available audio devices into the available_*_devices lists.
        static AudioDeviceEnumerator()
        {
            IntPtr        dummy_device  = IntPtr.Zero;
            ContextHandle dummy_context = ContextHandle.Zero;

            try
            {
                Debug.WriteLine("Enumerating audio devices.");
                Debug.Indent();

                // need a dummy context for correct results
                dummy_device  = Alc.OpenDevice(null);
                dummy_context = Alc.CreateContext(dummy_device, (int[])null);
                bool     dummy_success = Alc.MakeContextCurrent(dummy_context);
                AlcError dummy_error   = Alc.GetError(dummy_device);
                if (!dummy_success || dummy_error != AlcError.NoError)
                {
                    throw new AudioContextException("Failed to create dummy Context. Device (" + dummy_device.ToString() +
                                                    ") Context (" + dummy_context.Handle.ToString() +
                                                    ") MakeContextCurrent " + (dummy_success ? "succeeded" : "failed") +
                                                    ", Alc Error (" + dummy_error.ToString() + ") " + Alc.GetString(IntPtr.Zero, (AlcGetString)dummy_error));
                }

                // Get a list of all known playback devices, using best extension available
                if (Alc.IsExtensionPresent(IntPtr.Zero, "ALC_ENUMERATION_EXT"))
                {
                    version = AlcVersion.Alc1_1;
                    if (Alc.IsExtensionPresent(IntPtr.Zero, "ALC_ENUMERATE_ALL_EXT"))
                    {
                        available_playback_devices.AddRange(Alc.GetString(IntPtr.Zero, AlcGetStringList.AllDevicesSpecifier));
                        default_playback_device = Alc.GetString(IntPtr.Zero, AlcGetString.DefaultAllDevicesSpecifier);
                    }
                    else
                    {
                        available_playback_devices.AddRange(Alc.GetString(IntPtr.Zero, AlcGetStringList.DeviceSpecifier));
                        default_playback_device = Alc.GetString(IntPtr.Zero, AlcGetString.DefaultDeviceSpecifier);
                    }
                }
                else
                {
                    version = AlcVersion.Alc1_0;
                    Debug.Print("Device enumeration extension not available. Failed to enumerate playback devices.");
                }
                AlcError playback_err = Alc.GetError(dummy_device);
                if (playback_err != AlcError.NoError)
                {
                    throw new AudioContextException("Alc Error occured when querying available playback devices. " + playback_err.ToString());
                }

                // Get a list of all known recording devices, at least ALC_ENUMERATION_EXT is needed too
                if (version == AlcVersion.Alc1_1 && Alc.IsExtensionPresent(IntPtr.Zero, "ALC_EXT_CAPTURE"))
                {
                    available_recording_devices.AddRange(Alc.GetString(IntPtr.Zero, AlcGetStringList.CaptureDeviceSpecifier));
                    default_recording_device = Alc.GetString(IntPtr.Zero, AlcGetString.CaptureDefaultDeviceSpecifier);
                }
                else
                {
                    Debug.Print("Capture extension not available. Failed to enumerate recording devices.");
                }
                AlcError record_err = Alc.GetError(dummy_device);
                if (record_err != AlcError.NoError)
                {
                    throw new AudioContextException("Alc Error occured when querying available recording devices. " + record_err.ToString());
                }

#if DEBUG
                Debug.WriteLine("Found playback devices:");
                foreach (string s in available_playback_devices)
                {
                    Debug.WriteLine(s);
                }

                Debug.WriteLine("Default playback device: " + default_playback_device);

                Debug.WriteLine("Found recording devices:");
                foreach (string s in available_recording_devices)
                {
                    Debug.WriteLine(s);
                }

                Debug.WriteLine("Default recording device: " + default_recording_device);
#endif
            }
            catch (DllNotFoundException e)
            {
                Trace.WriteLine(e.ToString());
                openal_supported = false;
            }
            catch (AudioContextException ace)
            {
                Trace.WriteLine(ace.ToString());
                openal_supported = false;
            }
            finally
            {
                Debug.Unindent();

                if (openal_supported)
                {
                    try
                    {
                        // clean up the dummy context
                        Alc.MakeContextCurrent(ContextHandle.Zero);
                        if (dummy_context != ContextHandle.Zero && dummy_context.Handle != IntPtr.Zero)
                        {
                            Alc.DestroyContext(dummy_context);
                        }
                        if (dummy_device != IntPtr.Zero)
                        {
                            Alc.CloseDevice(dummy_device);
                        }
                    }
                    catch
                    {
                        openal_supported = false;
                    }
                }
            }
        }
示例#8
0
        private VoipCapture(string deviceName) : base(GameMain.Client?.ID ?? 0, true, false)
        {
            Disconnected = false;

            VoipConfig.SetupEncoding();

            //set up capture device
            captureDevice = Alc.CaptureOpenDevice(deviceName, VoipConfig.FREQUENCY, Al.FormatMono16, VoipConfig.BUFFER_SIZE * 5);

            if (captureDevice == IntPtr.Zero)
            {
                DebugConsole.NewMessage("Alc.CaptureOpenDevice attempt 1 failed: error code " + Alc.GetError(IntPtr.Zero).ToString(), Color.Orange);
                //attempt using a smaller buffer size
                captureDevice = Alc.CaptureOpenDevice(deviceName, VoipConfig.FREQUENCY, Al.FormatMono16, VoipConfig.BUFFER_SIZE * 2);
            }

            if (captureDevice == IntPtr.Zero)
            {
                DebugConsole.NewMessage("Alc.CaptureOpenDevice attempt 2 failed: error code " + Alc.GetError(IntPtr.Zero).ToString(), Color.Orange);
                //attempt using the default device
                captureDevice = Alc.CaptureOpenDevice("", VoipConfig.FREQUENCY, Al.FormatMono16, VoipConfig.BUFFER_SIZE * 2);
            }

            if (captureDevice == IntPtr.Zero)
            {
                string errorCode = Alc.GetError(IntPtr.Zero).ToString();
                if (!GUIMessageBox.MessageBoxes.Any(mb => mb.UserData as string == "capturedevicenotfound"))
                {
                    GUI.SettingsMenuOpen = false;
                    new GUIMessageBox(TextManager.Get("Error"),
                                      (TextManager.Get("VoipCaptureDeviceNotFound", returnNull: true) ?? "Could not start voice capture, suitable capture device not found.") + " (" + errorCode + ")")
                    {
                        UserData = "capturedevicenotfound"
                    };
                }
                GameAnalyticsManager.AddErrorEventOnce("Alc.CaptureDeviceOpenFailed", GameAnalyticsSDK.Net.EGAErrorSeverity.Error,
                                                       "Alc.CaptureDeviceOpen(" + deviceName + ") failed. Error code: " + errorCode);
                GameMain.Config.VoiceSetting = GameSettings.VoiceMode.Disabled;
                Instance?.Dispose();
                Instance = null;
                return;
            }

            int alError  = Al.GetError();
            int alcError = Alc.GetError(captureDevice);

            if (alcError != Alc.NoError)
            {
                throw new Exception("Failed to open capture device: " + alcError.ToString() + " (ALC)");
            }
            if (alError != Al.NoError)
            {
                throw new Exception("Failed to open capture device: " + alError.ToString() + " (AL)");
            }

            CanDetectDisconnect = Alc.IsExtensionPresent(captureDevice, "ALC_EXT_disconnect");
            alcError            = Alc.GetError(captureDevice);
            if (alcError != Alc.NoError)
            {
                throw new Exception("Error determining if disconnect can be detected: " + alcError.ToString());
            }

            Alc.CaptureStart(captureDevice);
            alcError = Alc.GetError(captureDevice);
            if (alcError != Alc.NoError)
            {
                throw new Exception("Failed to start capturing: " + alcError.ToString());
            }

            capturing     = true;
            captureThread = new Thread(UpdateCapture)
            {
                IsBackground = true,
                Name         = "VoipCapture"
            };
            captureThread.Start();
        }
示例#9
0
        public bool InitializeAlcDevice(string deviceName)
        {
            ReleaseResources(true);

            DebugConsole.NewMessage($"Attempting to open ALC device \"{deviceName}\"");

            alcDevice = IntPtr.Zero;
            int alcError = Al.NoError;

            for (int i = 0; i < 3; i++)
            {
                alcDevice = Alc.OpenDevice(deviceName);
                if (alcDevice == IntPtr.Zero)
                {
                    alcError = Alc.GetError(IntPtr.Zero);
                    DebugConsole.NewMessage($"ALC device initialization attempt #{i + 1} failed: device is null (error code {Alc.GetErrorString(alcError)})");
                    if (!string.IsNullOrEmpty(deviceName))
                    {
                        deviceName = null;
                        DebugConsole.NewMessage($"Switching to default device...");
                    }
                }
                else
                {
                    alcError = Alc.GetError(alcDevice);
                    if (alcError != Alc.NoError)
                    {
                        DebugConsole.NewMessage($"ALC device initialization attempt #{i + 1} failed: error code {Alc.GetErrorString(alcError)}");
                        bool closed = Alc.CloseDevice(alcDevice);
                        if (!closed)
                        {
                            DebugConsole.NewMessage($"Failed to close ALC device");
                        }
                        alcDevice = IntPtr.Zero;
                    }
                    else
                    {
                        break;
                    }
                }
            }
            if (alcDevice == IntPtr.Zero)
            {
                DebugConsole.ThrowError("ALC device creation failed too many times!");
                Disabled = true;
                return(false);
            }

            CanDetectDisconnect = Alc.IsExtensionPresent(alcDevice, "ALC_EXT_disconnect");
            alcError            = Alc.GetError(alcDevice);
            if (alcError != Alc.NoError)
            {
                DebugConsole.ThrowError("Error determining if disconnect can be detected: " + alcError.ToString() + ". Disabling audio playback...");
                Disabled = true;
                return(false);
            }

            Disconnected = false;

            int[] alcContextAttrs = new int[] { };
            alcContext = Alc.CreateContext(alcDevice, alcContextAttrs);
            if (alcContext == null)
            {
                DebugConsole.ThrowError("Failed to create an ALC context! (error code: " + Alc.GetError(alcDevice).ToString() + "). Disabling audio playback...");
                Disabled = true;
                return(false);
            }

            if (!Alc.MakeContextCurrent(alcContext))
            {
                DebugConsole.ThrowError("Failed to assign the current ALC context! (error code: " + Alc.GetError(alcDevice).ToString() + "). Disabling audio playback...");
                Disabled = true;
                return(false);
            }

            alcError = Alc.GetError(alcDevice);
            if (alcError != Alc.NoError)
            {
                DebugConsole.ThrowError("Error after assigning ALC context: " + Alc.GetErrorString(alcError) + ". Disabling audio playback...");
                Disabled = true;
                return(false);
            }

            Al.DistanceModel(Al.LinearDistanceClamped);

            int alError = Al.GetError();

            if (alError != Al.NoError)
            {
                DebugConsole.ThrowError("Error setting distance model: " + Al.GetErrorString(alError) + ". Disabling audio playback...");
                Disabled = true;
                return(false);
            }

            sourcePools[(int)SourcePoolIndex.Default] = new SoundSourcePool(SOURCE_COUNT);
            sourcePools[(int)SourcePoolIndex.Voice]   = new SoundSourcePool(16);

            ReloadSounds();

            Disabled = false;

            return(true);
        }
示例#10
0
 /// <summary>Get whether the extension with the given name is present.</summary>
 /// <param name="extensionName">The name of the extension to test.</param>
 /// <returns>Wehther the extension exists.</returns>
 public bool IsExtensionPresent(string extensionName)
 {
     return(Alc.IsExtensionPresent(Handle, extensionName));
 }
示例#11
0
        public SoundManager()
        {
            loadedSounds    = new List <Sound>();
            playingChannels = new SoundChannel[SOURCE_COUNT];

            streamingThread = null;

            categoryModifiers = null;

            alcDevice = Alc.OpenDevice(null);
            if (alcDevice == null)
            {
                throw new Exception("Failed to open an ALC device!");
            }

            AlcError alcError = Alc.GetError(alcDevice);

            if (alcError != AlcError.NoError)
            {
                //The audio device probably wasn't ready, this happens quite often
                //Just wait a while and try again
                Thread.Sleep(100);

                alcDevice = Alc.OpenDevice(null);

                alcError = Alc.GetError(alcDevice);
                if (alcError != AlcError.NoError)
                {
                    throw new Exception("Error initializing ALC device: " + alcError.ToString());
                }
            }

            int[] alcContextAttrs = new int[] { };
            alcContext = Alc.CreateContext(alcDevice, alcContextAttrs);
            if (alcContext == null)
            {
                throw new Exception("Failed to create an ALC context! (error code: " + Alc.GetError(alcDevice).ToString() + ")");
            }

            if (!Alc.MakeContextCurrent(alcContext))
            {
                throw new Exception("Failed to assign the current ALC context! (error code: " + Alc.GetError(alcDevice).ToString() + ")");
            }

            alcError = Alc.GetError(alcDevice);
            if (alcError != AlcError.NoError)
            {
                throw new Exception("Error after assigning ALC context: " + alcError.ToString());
            }

            ALError alError = ALError.NoError;

            alSources = new uint[SOURCE_COUNT];
            for (int i = 0; i < SOURCE_COUNT; i++)
            {
                AL.GenSource(out alSources[i]);
                alError = AL.GetError();
                if (alError != ALError.NoError)
                {
                    throw new Exception("Error generating alSource[" + i.ToString() + "]: " + AL.GetErrorString(alError));
                }

                if (!AL.IsSource(alSources[i]))
                {
                    throw new Exception("Generated alSource[" + i.ToString() + "] is invalid!");
                }

                AL.SourceStop(alSources[i]);
                alError = AL.GetError();
                if (alError != ALError.NoError)
                {
                    throw new Exception("Error stopping newly generated alSource[" + i.ToString() + "]: " + AL.GetErrorString(alError));
                }

                AL.Source(alSources[i], ALSourcef.MinGain, 0.0f);
                alError = AL.GetError();
                if (alError != ALError.NoError)
                {
                    throw new Exception("Error setting min gain: " + AL.GetErrorString(alError));
                }

                AL.Source(alSources[i], ALSourcef.MaxGain, 1.0f);
                alError = AL.GetError();
                if (alError != ALError.NoError)
                {
                    throw new Exception("Error setting max gain: " + AL.GetErrorString(alError));
                }

                AL.Source(alSources[i], ALSourcef.RolloffFactor, 1.0f);
                alError = AL.GetError();
                if (alError != ALError.NoError)
                {
                    throw new Exception("Error setting rolloff factor: " + AL.GetErrorString(alError));
                }
            }

            AL.DistanceModel(ALDistanceModel.LinearDistanceClamped);

            alError = AL.GetError();
            if (alError != ALError.NoError)
            {
                throw new Exception("Error setting distance model: " + AL.GetErrorString(alError));
            }

            if (Alc.IsExtensionPresent(IntPtr.Zero, "ALC_EXT_CAPTURE"))
            {
                alcCaptureDeviceNames = new List <string>(Alc.GetString(IntPtr.Zero, AlcGetStringList.CaptureDeviceSpecifier));
            }
            else
            {
                alcCaptureDeviceNames = null;
            }

            listenerOrientation  = new float[6];
            ListenerPosition     = Vector3.Zero;
            ListenerTargetVector = new Vector3(0.0f, 0.0f, 1.0f);
            ListenerUpVector     = new Vector3(0.0f, -1.0f, 0.0f);
        }
示例#12
0
        /// \internal
        /// <summary>Creates the audio context using the specified device.</summary>
        /// <param name="device">The device descriptor obtained through AudioContext.AvailableDevices, or null for the default device.</param>
        /// <param name="freq">Frequency for mixing output buffer, in units of Hz. Pass 0 for driver default.</param>
        /// <param name="refresh">Refresh intervals, in units of Hz. Pass 0 for driver default.</param>
        /// <param name="sync">Flag, indicating a synchronous context.</param>
        /// <param name="enableEfx">Indicates whether the EFX extension should be initialized, if present.</param>
        /// <param name="efxAuxiliarySends">Requires EFX enabled. The number of desired Auxiliary Sends per source.</param>
        /// <exception cref="ArgumentOutOfRangeException">Occurs when a specified parameter is invalid.</exception>
        /// <exception cref="AudioDeviceException">
        /// Occurs when the specified device is not available, or is in use by another program.
        /// </exception>
        /// <exception cref="AudioContextException">
        /// Occurs when an audio context could not be created with the specified parameters.
        /// </exception>
        /// <exception cref="NotSupportedException">
        /// Occurs when an AudioContext already exists.</exception>
        /// <remarks>
        /// <para>For maximum compatibility, you are strongly recommended to use the default constructor.</para>
        /// <para>Multiple AudioContexts are not supported at this point.</para>
        /// <para>
        /// The number of auxilliary EFX sends depends on the audio hardware and drivers. Most Realtek devices, as well
        /// as the Creative SB Live!, support 1 auxilliary send. Creative's Audigy and X-Fi series support 4 sends.
        /// Values higher than supported will be clamped by the driver.
        /// </para>
        /// </remarks>
        private void CreateContext(string device, int freq, int refresh, bool sync, bool enableEfx, MaxAuxiliarySends efxAuxiliarySends)
        {
            if (!AudioDeviceEnumerator.IsOpenALSupported)
            {
                throw new DllNotFoundException("openal32.dll");
            }

            if (AudioDeviceEnumerator.Version == AudioDeviceEnumerator.AlcVersion.Alc1_1 && AudioDeviceEnumerator.AvailablePlaybackDevices.Count == 0)    // Alc 1.0 does not support device enumeration.
            {
                throw new NotSupportedException("No audio hardware is available.");
            }
            if (context_exists)
            {
                throw new NotSupportedException("Multiple AudioContexts are not supported.");
            }
            if (freq < 0)
            {
                throw new ArgumentOutOfRangeException("freq", freq, "Should be greater than zero.");
            }
            if (refresh < 0)
            {
                throw new ArgumentOutOfRangeException("refresh", refresh, "Should be greater than zero.");
            }


            if (!String.IsNullOrEmpty(device))
            {
                device_name = device;
                Device      = Alc.OpenDevice(device); // try to open device by name
            }
            if (Device == IntPtr.Zero)
            {
                device_name = "IntPtr.Zero (null string)";
                Device      = Alc.OpenDevice(null); // try to open unnamed default device
            }
            if (Device == IntPtr.Zero)
            {
                device_name = AudioContext.DefaultDevice;
                Device      = Alc.OpenDevice(AudioContext.DefaultDevice); // try to open named default device
            }
            if (Device == IntPtr.Zero)
            {
                device_name = "None";
                throw new AudioDeviceException(String.Format("Audio device '{0}' does not exist or is tied up by another application.",
                                                             String.IsNullOrEmpty(device) ? "default" : device));
            }

            CheckErrors();

            // Build the attribute list
            List <int> attributes = new List <int>();

            if (freq != 0)
            {
                attributes.Add((int)AlcContextAttributes.Frequency);
                attributes.Add(freq);
            }

            if (refresh != 0)
            {
                attributes.Add((int)AlcContextAttributes.Refresh);
                attributes.Add(refresh);
            }

            attributes.Add((int)AlcContextAttributes.Sync);
            attributes.Add(sync ? 1 : 0);

            if (enableEfx && Alc.IsExtensionPresent(Device, "ALC_EXT_EFX"))
            {
                int num_slots;
                switch (efxAuxiliarySends)
                {
                case MaxAuxiliarySends.One:
                case MaxAuxiliarySends.Two:
                case MaxAuxiliarySends.Three:
                case MaxAuxiliarySends.Four:
                    num_slots = (int)efxAuxiliarySends;
                    break;

                default:
                case MaxAuxiliarySends.UseDriverDefault:
                    Alc.GetInteger(Device, AlcGetInteger.EfxMaxAuxiliarySends, 1, out num_slots);
                    break;
                }

                attributes.Add((int)AlcContextAttributes.EfxMaxAuxiliarySends);
                attributes.Add(num_slots);
            }
            attributes.Add(0);

            context_handle = Alc.CreateContext(Device, attributes.ToArray());

            if (context_handle == ContextHandle.Zero)
            {
                Alc.CloseDevice(Device);
                throw new AudioContextException("The audio context could not be created with the specified parameters.");
            }

            CheckErrors();

            // HACK: OpenAL SI on Linux/ALSA crashes on MakeCurrent. This hack avoids calling MakeCurrent when
            // an old OpenAL version is detect - it may affect outdated OpenAL versions different than OpenAL SI,
            // but it looks like a good compromise for now.
            if (AudioDeviceEnumerator.AvailablePlaybackDevices.Count > 0)
            {
                MakeCurrent();
            }

            CheckErrors();

            device_name = Alc.GetString(Device, AlcGetString.DeviceSpecifier);


            lock (audio_context_lock)
            {
                available_contexts.Add(this.context_handle, this);
                context_exists = true;
            }
        }