示例#1
0
        private void FillBuffer()
        {
            if (overrideSound != null)
            {
                int totalSampleCount = 0;
                while (totalSampleCount < VoipConfig.BUFFER_SIZE)
                {
                    int sampleCount = overrideSound.FillStreamBuffer(overridePos, overrideBuf);
                    overridePos += sampleCount * 2;
                    Array.Copy(overrideBuf, 0, uncompressedBuffer, totalSampleCount, sampleCount);
                    totalSampleCount += sampleCount;

                    if (sampleCount == 0)
                    {
                        overridePos = 0;
                    }
                }
                int sleepMs = VoipConfig.BUFFER_SIZE * 800 / VoipConfig.FREQUENCY;
                Thread.Sleep(sleepMs - 1);
            }
            else
            {
                int sampleCount = 0;

                while (sampleCount < VoipConfig.BUFFER_SIZE)
                {
                    Alc.GetInteger(captureDevice, Alc.EnumCaptureSamples, out sampleCount);

                    int alcError = Alc.GetError(captureDevice);
                    if (alcError != Alc.NoError)
                    {
                        throw new Exception("Failed to determine sample count: " + alcError.ToString());
                    }

                    if (sampleCount < VoipConfig.BUFFER_SIZE)
                    {
                        int sleepMs = (VoipConfig.BUFFER_SIZE - sampleCount) * 800 / VoipConfig.FREQUENCY;
                        if (sleepMs >= 1)
                        {
                            Thread.Sleep(sleepMs);
                        }
                    }

                    if (!capturing)
                    {
                        return;
                    }
                }

                Alc.CaptureSamples(captureDevice, nativeBuffer, VoipConfig.BUFFER_SIZE);
                Marshal.Copy(nativeBuffer, uncompressedBuffer, 0, uncompressedBuffer.Length);
            }
        }
        internal int GetQueuedSampleCount()
        {
            if (_state == MicrophoneState.Stopped || BufferReady == null)
            {
                return(0);
            }

            int[] values = new int[1];
            Alc.GetInteger(_captureDevice, AlcGetInteger.CaptureSamples, 1, values);

            CheckALCError("Failed to query capture samples.");

            return(values[0]);
        }
        public void ChangeAudioDevice(string DeviceName)
        {
            this.Device = Alc.OpenDevice(DeviceName);

            this.AudioContext = Alc.CreateContext(Device, (int[])null);
            Alc.MakeContextCurrent(AudioContext);

            Alc.GetInteger(Device, AlcGetInteger.AttributesSize, 1, out int size);
            int[] data = new int[size];
            Alc.GetInteger(Device, AlcGetInteger.AllAttributes, size, data);
            this.MaxSourceCount = data[Alc.GetEnumValue(Device, "ALC_MONO_SOURCES")];//ここあやしい

            Sources = AL.GenSources(MaxSourceCount);
        }
示例#4
0
        public AudioDevice(string deviceName)
        {
            if (deviceName != null && !AvailableDevices.Contains(deviceName))
            {
                throw new InvalidOperationException(string.Format("AudioDevice \"{0}\" does not exist.", deviceName));
            }

            Context = new OpenTK.Audio.AudioContext(deviceName, 0, 15, true, true, AudioContext.MaxAuxiliarySends.UseDriverDefault);
            CheckAlcError();
            deviceHandle = Alc.GetContextsDevice(Alc.GetCurrentContext());
            CheckAlcError();
            Efx = new EffectsExtension();
            CheckAlcError();

            int[] val = new int[4];
            DeviceName    = Context.CurrentDevice;
            VendorName    = AL.Get(ALGetString.Vendor);
            Renderer      = AL.Get(ALGetString.Renderer);
            DriverVersion = AL.Get(ALGetString.Version);
            int major, minor;

            Alc.GetInteger(deviceHandle, AlcGetInteger.MajorVersion, 1, val);
            major = val[0];
            Alc.GetInteger(deviceHandle, AlcGetInteger.MinorVersion, 1, val);
            minor   = val[0];
            Version = new Version(major, minor);
            Alc.GetInteger(deviceHandle, AlcGetInteger.EfxMajorVersion, 1, val);
            major = val[0];
            Alc.GetInteger(deviceHandle, AlcGetInteger.EfxMinorVersion, 1, val);
            minor      = val[0];
            EfxVersion = new Version(major, minor);
            Alc.GetInteger(deviceHandle, AlcGetInteger.EfxMaxAuxiliarySends, 1, val);
            MaxRoutes  = val[0];
            Extensions = new List <string>(AL.Get(ALGetString.Extensions).Split(' ')).AsReadOnly();

            AL.DistanceModel(ALDistanceModel.ExponentDistance);

            CheckAudioCapabilities(LogLevel.Verbose);
            LogDiagnostics(LogLevel.Verbose);

            Factory  = new AudioFactory(this);
            Listener = new AudioListener(this);
            Listener.Orientation(Vector3.UnitY, Vector3.UnitZ);

            updateTaskCancelation = new CancellationTokenSource();
            updateTask            = Task.Factory.StartNew(Update);
        }
        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));
            }
        }
示例#6
0
        private OpenALSoundController()
        {
            try
            {
                this.context = new AudioContext();
            }
            catch (Exception ex)
            {
                OpenALSoundController.Log("Last error in enumerator is " + AudioDeviceEnumerator.LastError);
                int num = (int)MessageBox.Show("Error initializing audio subsystem. Game will now exit.\n(see debug log for more details)", "OpenAL Error", MessageBoxButtons.OK, MessageBoxIcon.Hand);
                throw;
            }
            OpenALSoundController.Log("Sound manager initialized!");
            int[]  data1          = new int[1];
            IntPtr contextsDevice = Alc.GetContextsDevice(Alc.GetCurrentContext());

            Alc.GetInteger(contextsDevice, AlcGetInteger.AttributesSize, 1, data1);
            int[] data2 = new int[data1[0]];
            Alc.GetInteger(contextsDevice, AlcGetInteger.AllAttributes, data1[0], data2);
            for (int index = 0; index < data2.Length; ++index)
            {
                if (data2[index] == 4112)
                {
                    OpenALSoundController.Log("Available mono sources : " + (object)data2[index + 1]);
                    break;
                }
            }
            this.filterId = ALHelper.Efx.GenFilter();
            ALHelper.Efx.Filter(this.filterId, EfxFilteri.FilterType, 1);
            ALHelper.Efx.Filter(this.filterId, EfxFilterf.LowpassGain, 1f);
            ALHelper.Efx.Filter(this.filterId, EfxFilterf.LowpassGainHF, 1f);
            AL.DistanceModel(ALDistanceModel.InverseDistanceClamped);
            this.freeBuffers = new ConcurrentStack <int>();
            this.ExpandBuffers(256);
            this.allocatedBuffers   = new Dictionary <SoundEffect, OpenALSoundController.BufferAllocation>();
            this.staleAllocations   = new List <KeyValuePair <SoundEffect, OpenALSoundController.BufferAllocation> >();
            this.filteredSources    = new HashSet <int>();
            this.activeSoundEffects = new List <SoundEffectInstance>();
            this.freeSources        = new ConcurrentStack <int>();
            this.ExpandSources(64);
        }
示例#7
0
        private void UpdateCapture()
        {
            Array.Copy(uncompressedBuffer, 0, prevUncompressedBuffer, 0, VoipConfig.BUFFER_SIZE);
            Array.Clear(uncompressedBuffer, 0, VoipConfig.BUFFER_SIZE);
            while (capturing && !Disconnected)
            {
                int alcError;

                if (CanDetectDisconnect)
                {
                    Alc.GetInteger(captureDevice, Alc.EnumConnected, out int isConnected);
                    alcError = Alc.GetError(captureDevice);
                    if (alcError != Alc.NoError)
                    {
                        throw new Exception("Failed to determine if capture device is connected: " + alcError.ToString());
                    }

                    if (isConnected == 0)
                    {
                        DebugConsole.ThrowError("Capture device has been disconnected. You can select another available device in the settings.");
                        Disconnected = true;
                        break;
                    }
                }

                Alc.GetInteger(captureDevice, Alc.EnumCaptureSamples, out int sampleCount);

                alcError = Alc.GetError(captureDevice);
                if (alcError != Alc.NoError)
                {
                    throw new Exception("Failed to determine sample count: " + alcError.ToString());
                }

                if (sampleCount < VoipConfig.BUFFER_SIZE)
                {
                    int sleepMs = (VoipConfig.BUFFER_SIZE - sampleCount) * 800 / VoipConfig.FREQUENCY;
                    if (sleepMs < 5)
                    {
                        sleepMs = 5;
                    }
                    Thread.Sleep(sleepMs);
                    continue;
                }

                GCHandle handle = GCHandle.Alloc(uncompressedBuffer, GCHandleType.Pinned);
                try
                {
                    Alc.CaptureSamples(captureDevice, handle.AddrOfPinnedObject(), VoipConfig.BUFFER_SIZE);
                }
                finally
                {
                    handle.Free();
                }

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

                double maxAmplitude = 0.0f;
                for (int i = 0; i < VoipConfig.BUFFER_SIZE; i++)
                {
                    uncompressedBuffer[i] = (short)MathHelper.Clamp((uncompressedBuffer[i] * Gain), -short.MaxValue, short.MaxValue);
                    double sampleVal = uncompressedBuffer[i] / (double)short.MaxValue;
                    maxAmplitude = Math.Max(maxAmplitude, Math.Abs(sampleVal));
                }
                double dB = Math.Min(20 * Math.Log10(maxAmplitude), 0.0);

                LastdB        = dB;
                LastAmplitude = maxAmplitude;

                bool allowEnqueue = false;
                if (GameMain.WindowActive)
                {
                    ForceLocal = captureTimer > 0 ? ForceLocal : false;
                    bool pttDown = false;
                    if ((PlayerInput.KeyDown(InputType.Voice) || PlayerInput.KeyDown(InputType.LocalVoice)) &&
                        GUI.KeyboardDispatcher.Subscriber == null)
                    {
                        pttDown = true;
                        if (PlayerInput.KeyDown(InputType.LocalVoice))
                        {
                            ForceLocal = true;
                        }
                        else
                        {
                            ForceLocal = false;
                        }
                    }
                    if (GameMain.Config.VoiceSetting == GameSettings.VoiceMode.Activity)
                    {
                        if (dB > GameMain.Config.NoiseGateThreshold)
                        {
                            allowEnqueue = true;
                        }
                    }
                    else if (GameMain.Config.VoiceSetting == GameSettings.VoiceMode.PushToTalk)
                    {
                        if (pttDown)
                        {
                            allowEnqueue = true;
                        }
                    }
                }

                if (allowEnqueue || captureTimer > 0)
                {
                    LastEnqueueAudio = DateTime.Now;
                    if (GameMain.Client?.Character != null)
                    {
                        var messageType = !ForceLocal && ChatMessage.CanUseRadio(GameMain.Client.Character, out _) ? ChatMessageType.Radio : ChatMessageType.Default;
                        GameMain.Client.Character.ShowSpeechBubble(1.25f, ChatMessage.MessageColor[(int)messageType]);
                    }
                    //encode audio and enqueue it
                    lock (buffers)
                    {
                        if (!prevCaptured) //enqueue the previous buffer if not sent to avoid cutoff
                        {
                            int compressedCountPrev = VoipConfig.Encoder.Encode(prevUncompressedBuffer, 0, VoipConfig.BUFFER_SIZE, BufferToQueue, 0, VoipConfig.MAX_COMPRESSED_SIZE);
                            EnqueueBuffer(compressedCountPrev);
                        }
                        int compressedCount = VoipConfig.Encoder.Encode(uncompressedBuffer, 0, VoipConfig.BUFFER_SIZE, BufferToQueue, 0, VoipConfig.MAX_COMPRESSED_SIZE);
                        EnqueueBuffer(compressedCount);
                    }
                    captureTimer -= (VoipConfig.BUFFER_SIZE * 1000) / VoipConfig.FREQUENCY;
                    if (allowEnqueue)
                    {
                        captureTimer = GameMain.Config.VoiceChatCutoffPrevention;
                    }
                    prevCaptured = true;
                }
                else
                {
                    captureTimer = 0;
                    prevCaptured = false;
                    //enqueue silence
                    lock (buffers)
                    {
                        EnqueueBuffer(0);
                    }
                }

                Thread.Sleep(10);
            }
        }
示例#8
0
        public void Update()
        {
            if (Disconnected || Disabled)
            {
                return;
            }

            if (CanDetectDisconnect)
            {
                Alc.GetInteger(alcDevice, Alc.EnumConnected, out int isConnected);
                int alcError = Alc.GetError(alcDevice);
                if (alcError != Alc.NoError)
                {
                    throw new Exception("Failed to determine if device is connected: " + alcError.ToString());
                }

                if (isConnected == 0)
                {
                    DebugConsole.ThrowError("Playback device has been disconnected. You can select another available device in the settings.");
                    GameMain.Config.AudioOutputDevice = "<disconnected>";
                    Disconnected = true;
                    return;
                }
            }

            if (GameMain.Client != null && GameMain.Config.VoipAttenuationEnabled)
            {
                if (Timing.TotalTime > lastAttenuationTime + 0.2)
                {
                    voipAttenuatedGain = voipAttenuatedGain * 0.9f + 0.1f;
                }
            }
            else
            {
                voipAttenuatedGain = 1.0f;
            }
            SetCategoryGainMultiplier("default", VoipAttenuatedGain, 1);
            SetCategoryGainMultiplier("ui", VoipAttenuatedGain, 1);
            SetCategoryGainMultiplier("waterambience", VoipAttenuatedGain, 1);
            SetCategoryGainMultiplier("music", VoipAttenuatedGain, 1);

            if (GameMain.Config.DynamicRangeCompressionEnabled)
            {
                float targetGain = (Math.Min(1.0f, 1.0f / PlaybackAmplitude) - 1.0f) * 0.5f + 1.0f;
                if (targetGain < CompressionDynamicRangeGain)
                {
                    //if the target gain is lower than the current gain, lower the current gain immediately to prevent clipping
                    CompressionDynamicRangeGain = targetGain;
                }
                else
                {
                    //otherwise, let it rise back smoothly
                    CompressionDynamicRangeGain = (targetGain) * 0.05f + CompressionDynamicRangeGain * 0.95f;
                }
            }
            else
            {
                CompressionDynamicRangeGain = 1.0f;
            }

            if (streamingThread == null || streamingThread.ThreadState.HasFlag(ThreadState.Stopped))
            {
                bool startedStreamThread = false;
                for (int i = 0; i < playingChannels.Length; i++)
                {
                    lock (playingChannels[i])
                    {
                        for (int j = 0; j < playingChannels[i].Length; j++)
                        {
                            if (playingChannels[i][j] == null)
                            {
                                continue;
                            }
                            if (playingChannels[i][j].IsStream && playingChannels[i][j].IsPlaying)
                            {
                                InitStreamThread();
                                startedStreamThread = true;
                            }
                            if (startedStreamThread)
                            {
                                break;
                            }
                        }
                    }
                    if (startedStreamThread)
                    {
                        break;
                    }
                }
            }
        }
示例#9
0
 internal static int[] StaticGetInt(AlcGetInteger param, int[] list)
 {
     Alc.GetInteger(IntPtr.Zero, param, list.Length, list); return(list);
 }
示例#10
0
 internal static int StaticGetInt(AlcGetInteger param)
 {
     int result; Alc.GetInteger(IntPtr.Zero, param, 1, out result); return(result);
 }
示例#11
0
 internal int[] GetInt(AlcGetInteger param, int[] list)
 {
     Alc.GetInteger(Handle, param, list.Length, list); return(list);
 }
示例#12
0
 internal int GetInt(AlcGetInteger param)
 {
     int result; Alc.GetInteger(Handle, param, 1, out result); return(result);
 }
示例#13
0
        protected bool init()
        {
            if (myIsInitialized == true)
            {
                return(true);
            }


            Info.print("------------------AUDIO MANAGER----------------");

            try
            {
                //try to get the DirectSound default (openAL-soft's target)
                string defaultDevice = AudioContext.DefaultDevice;
                myContext = new AudioContext(defaultDevice);
            }
            catch (AudioException ex)
            {
                Error.print("Exception trying to initialize OpenAL Context.  Verify OpenAL drivers are installed");
                Error.print("Exception: {0}", ex.Message);
                if (ex.InnerException != null)
                {
                    Error.print("Inner Exception: {0}", ex.InnerException.Message);
                }

                return(false);
            }

            //make the context current
            myContext.MakeCurrent();
            myContext.CheckErrors();
            myDevice = Alc.GetContextsDevice(Alc.GetCurrentContext());

            //print out the attributs
            int attributeSize = 0;

            Alc.GetInteger(myDevice, AlcGetInteger.AttributesSize, 1, out attributeSize);
            int[] attBuffer = new int[attributeSize * 2 + 1];
            Alc.GetInteger(myDevice, AlcGetInteger.AllAttributes, attributeSize * 2 + 1, attBuffer);
            int idx = 0;

            while (attBuffer[idx] != 0)
            {
                Info.print(String.Format("Context attribute: {0}:{1}", Audio.enumToString(attBuffer[idx]), attBuffer[idx + 1]));
                idx += 2;
            }

            //print some debug information about the system
            string alExtensions  = AL.Get(ALGetString.Extensions);
            string alcExtensions = Alc.GetString(myDevice, AlcGetString.Extensions);

            Info.print("Opened Audio device {0}", myContext.ToString());
            Info.print("OpenAL Vendor: {0}", AL.Get(ALGetString.Vendor));
            Info.print("OpenAL Version: {0}", AL.Get(ALGetString.Version));
            Info.print("OpenAL Renderer: {0}", AL.Get(ALGetString.Renderer));
            Info.print("OpenAL Extensions: {0}", AL.Get(ALGetString.Extensions));
            Info.print("OpenAL Context Extensions: {0} ", Alc.GetString(myDevice, AlcGetString.Extensions));



            string[] extensions = alcExtensions.Split(' ');
            for (int i = 0; i < extensions.Length; i++)
            {
                if (extensions[i] == "ALC_EXT_EFX")
                {
                    myEnvironmentalProcessingAvailable = true;
                }
            }

            Info.print("Environmental Processing: " + (myEnvironmentalProcessingAvailable ? "available" : "unavailable"));

            createVoices(myMaxVoices);

            Info.print("------------------AUDIO MANAGER----------------");

            return(true);
        }
示例#14
0
        void UpdateCapture()
        {
            short[] uncompressedBuffer = new short[VoipConfig.BUFFER_SIZE];
            while (capturing)
            {
                int alcError;
                Alc.GetInteger(captureDevice, Alc.EnumCaptureSamples, out int sampleCount);

                alcError = Alc.GetError(captureDevice);
                if (alcError != Alc.NoError)
                {
                    throw new Exception("Failed to determine sample count: " + alcError.ToString());
                }

                if (sampleCount < VoipConfig.BUFFER_SIZE)
                {
                    int sleepMs = (VoipConfig.BUFFER_SIZE - sampleCount) * 800 / VoipConfig.FREQUENCY;
                    if (sleepMs < 5)
                    {
                        sleepMs = 5;
                    }
                    Thread.Sleep(sleepMs);
                    continue;
                }

                GCHandle handle = GCHandle.Alloc(uncompressedBuffer, GCHandleType.Pinned);
                try
                {
                    Alc.CaptureSamples(captureDevice, handle.AddrOfPinnedObject(), VoipConfig.BUFFER_SIZE);
                }
                finally
                {
                    handle.Free();
                }

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

                double maxAmplitude = 0.0f;
                for (int i = 0; i < VoipConfig.BUFFER_SIZE; i++)
                {
                    uncompressedBuffer[i] = (short)MathHelper.Clamp((uncompressedBuffer[i] * Gain), -short.MaxValue, short.MaxValue);
                    double sampleVal = uncompressedBuffer[i] / (double)short.MaxValue;
                    maxAmplitude = Math.Max(maxAmplitude, Math.Abs(sampleVal));
                }
                double dB = Math.Min(20 * Math.Log10(maxAmplitude), 0.0);

                LastdB = dB;

                bool allowEnqueue = false;
                if (GameMain.WindowActive)
                {
                    if (GameMain.Config.VoiceSetting == GameSettings.VoiceMode.Activity)
                    {
                        if (dB > GameMain.Config.NoiseGateThreshold)
                        {
                            allowEnqueue = true;
                        }
                    }
                    else if (GameMain.Config.VoiceSetting == GameSettings.VoiceMode.PushToTalk)
                    {
                        if (PlayerInput.KeyDown(InputType.Voice) && GUI.KeyboardDispatcher.Subscriber == null)
                        {
                            allowEnqueue = true;
                        }
                    }
                }

                if (allowEnqueue)
                {
                    LastEnqueueAudio = DateTime.Now;
                    //encode audio and enqueue it
                    lock (buffers)
                    {
                        int compressedCount = VoipConfig.Encoder.Encode(uncompressedBuffer, 0, VoipConfig.BUFFER_SIZE, BufferToQueue, 0, VoipConfig.MAX_COMPRESSED_SIZE);
                        EnqueueBuffer(compressedCount);
                    }
                }
                else
                {
                    //enqueue silence
                    lock (buffers)
                    {
                        EnqueueBuffer(0);
                    }
                }

                Thread.Sleep(10);
            }
        }
示例#15
0
        public static void AlcUnitTestFunc()
        {
            AudioContext context = new AudioContext();

            Trace.WriteLine("Testing AudioContext functions.");
            Trace.Indent();

//            Trace.WriteLine("Suspend()...");
//            context.Suspend();
//            Trace.Assert(!context.IsProcessing);
//
//            Trace.WriteLine("Process()...");
//            context.Process();
//            Trace.Assert(context.IsProcessing);

            //Trace.WriteLine("MakeCurrent()...");
            //context.MakeCurrent();
            //Trace.Assert(context.IsCurrent);

            //Trace.WriteLine("IsCurrent = false...");
            //context.IsCurrent = false;
            //Trace.Assert(!context.IsCurrent);

            //Trace.WriteLine("IsCurrent = true...");
            //context.IsCurrent = true;
            //Trace.Assert(context.IsCurrent);

            Trace.WriteLine("AudioContext.CurrentContext...");
            Trace.Assert(AudioContext.CurrentContext == context);

            #region Get Attribs

            //int AttribCount;
            //Alc.GetInteger(context.Device, AlcGetInteger.AttributesSize, sizeof(int), out AttribCount);
            //Trace.WriteLine("AttributeSize: " + AttribCount);

            //if (AttribCount > 0)
            //{
            //    int[] Attribs = new int[AttribCount];
            //    Alc.GetInteger(context.Device, AlcGetInteger.AllAttributes, AttribCount, out Attribs[0]);
            //    for (int i = 0; i < Attribs.Length; i++)
            //    {
            //        Trace.Write(Attribs[i]);
            //        Trace.Write(" ");
            //    }
            //    Trace.WriteLine();
            //}

            #endregion Get Attribs

#if false
            AlDevice  MyDevice;
            AlContext MyContext;

            // Initialize Open AL
            MyDevice = Alc.OpenDevice(null);  // open default device
            if (MyDevice != Al.Null)
            {
                Trace.WriteLine("Device allocation succeeded.");
                MyContext = Alc.CreateContext(MyDevice, Al.Null);   // create context
                if (MyContext != Al.Null)
                {
                    Trace.WriteLine("Context allocation succeeded.");
                    GetOpenALErrors(MyDevice);

                    Alc.SuspendContext(MyContext);                      // disable context
                    Alc.ProcessContext(MyContext);                      // enable context. The default state of a context created by alcCreateContext is that it is processing.
                    Al.Bool result = Alc.MakeContextCurrent(MyContext); // set active context
                    Trace.WriteLine("MakeContextCurrent succeeded? " + result);
                    GetOpenALErrors(MyDevice);

                    Trace.WriteLine("Default: " + Alc.GetString(MyDevice, Enums.AlcGetString.DefaultDeviceSpecifier));
                    Trace.WriteLine("Device: " + Alc.GetString(MyDevice, Enums.AlcGetString.DeviceSpecifier));
                    Trace.WriteLine("Extensions: " + Alc.GetString(MyDevice, Enums.AlcGetString.Extensions));
                    GetOpenALErrors(MyDevice);

                    #region Get Attribs
                    int AttribCount;
                    Alc.GetInteger(MyDevice, Enums.AlcGetInteger.AttributesSize, sizeof(int), out AttribCount);
                    Trace.WriteLine("AttributeSize: " + AttribCount);

                    if (AttribCount > 0)
                    {
                        int[] Attribs = new int[AttribCount];
                        Alc.GetInteger(MyDevice, Enums.AlcGetInteger.AttributesSize, AttribCount, out Attribs[0]);
                        for (int i = 0; i < Attribs.Length; i++)
                        {
                            Trace.Write(", " + Attribs[i]);
                        }
                        Trace.WriteLine( );
                    }
                    #endregion Get Attribs
                    GetOpenALErrors(MyDevice);

                    AlDevice  currdev = Alc.GetContextsDevice(MyContext);
                    AlContext currcon = Alc.GetCurrentContext( );

                    if (MyDevice == currdev)
                    {
                        Trace.WriteLine("Devices match.");
                    }
                    else
                    {
                        Trace.WriteLine("Error: Devices do not match.");
                    }

                    if (MyContext == currcon)
                    {
                        Trace.WriteLine("Context match.");
                    }
                    else
                    {
                        Trace.WriteLine("Error: Contexts do not match.");
                    }

                    // exit
                    Alc.MakeContextCurrent(Al.Null);   // results in no context being current
                    Alc.DestroyContext(MyContext);
                    result = Alc.CloseDevice(MyDevice);
                    Trace.WriteLine("Result: " + result);
                    Trace.ReadLine( );
                }
                else
                {
                    Trace.WriteLine("Context creation failed.");
                }
            }
            else
            {
                Trace.WriteLine("Failed to find suitable Device.");
            }
#endif

            /*
             * include <stdlib.h>
             * include <AL/alut.h>
             *
             * int
             * main (int argc, char **argv)
             * {
             * ALuint helloBuffer, helloSource;
             * alutInit (&argc, argv);
             * helloBuffer = alutCreateBufferHelloWorld ();  alGenSources (1, &helloSource);
             * alSourcei (helloSource, AL_Buffer, helloBuffer);
             * alSourcePlay (helloSource);
             * alutSleep (1);
             * alutExit ();
             * return EXIT_SUCCESS;
             * }*/

            /*
             *
             * Processing Loop Example:
             * // PlaceCamera - places OpenGL camera & updates OpenAL listener buffer
             * void AVEnvironment::PlaceCamera()
             * {
             * // update OpenGL camera position
             * glMatrixMode(GL_PROJECTION);
             * glLoadIdentity();
             * glFrustum(-0.1333, 0.1333, -0.1, 0.1, 0.2, 50.0);
             * gluLookAt(listenerPos[0], listenerPos[1], listenerPos[2],
             * (listenerPos[0] + sin(listenerAngle)), listenerPos[1],
             * (listenerPos[2] - cos(listenerAngle)),
             * 0.0, 1.0, 0.0);
             * // update OpenAL
             * // place listener at camera
             * alListener3f(AL_POSITION, listenerPos[0], listenerPos[1], listenerPos[2]);
             * float directionvect[6];
             * directionvect[0] = (float) sin(listenerAngle);
             * directionvect[1] = 0;
             * directionvect[2] = (float) cos(listenerAngle);
             * directionvect[3] = 0;
             * directionvect[4] = 1;
             * directionvect[5] = 0;
             * alListenerfv(AL_ORIENTATION, directionvect);
             * }
             *
             */
        }
示例#16
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;
            }
        }