Пример #1
0
        public OpenALAudioLayer(string name, OpenALAudioAdapter parent) : base(name)
        {
            if (_openALFormatId == 0)
            {
                _openALFormatId = _openALAudioFormat.BitsPerSample switch
                {
                    32 => Al.FORMAT_STEREO32F,
                    16 => _openALAudioFormat.Channels == 2 ? Al.FORMAT_STEREO16 : Al.FORMAT_MONO16,
                    8 => _openALAudioFormat.Channels == 2 ? Al.FORMAT_STEREO8 : Al.FORMAT_MONO8,
                    _ => _openALFormatId
                }
            }
            ;

            if (_frameRequestSize == 0)
            {
                _frameRequestSize  = _openALAudioFormat.GetFrameCount(BackendBufferExpectedAhead / 1000f);
                _frameRequestSize /= BUFFER_COUNT;
            }

            _parent = parent;
            Al.GenSource(out _source);

            _buffers    = new uint[BUFFER_COUNT];
            _bufferBusy = new bool[BUFFER_COUNT];
            for (var i = 0; i < _buffers.Length; i++)
            {
                Al.GenBuffer(out _buffers[i]);
            }

            _uploadBuffer = new byte[_frameRequestSize * _openALAudioFormat.FrameSize];
        }
Пример #2
0
        public virtual void InitializeALBuffers()
        {
            if (!Stream)
            {
                Al.GenBuffer(out alBuffer);
                int alError = Al.GetError();
                if (alError != Al.NoError)
                {
                    throw new Exception("Failed to create OpenAL buffer for non-streamed sound: " + Al.GetErrorString(alError));
                }

                if (!Al.IsBuffer(alBuffer))
                {
                    throw new Exception("Generated OpenAL buffer is invalid!");
                }

                Al.GenBuffer(out alMuffledBuffer);
                alError = Al.GetError();
                if (alError != Al.NoError)
                {
                    throw new Exception("Failed to create OpenAL buffer for non-streamed sound: " + Al.GetErrorString(alError));
                }

                if (!Al.IsBuffer(alMuffledBuffer))
                {
                    throw new Exception("Generated OpenAL buffer is invalid!");
                }
            }
            else
            {
                alBuffer = 0;
            }
        }
Пример #3
0
        internal unsafe AudioClip(IResource resource)
        {
            Al.GenBuffer(out Buffer);

            using var reader = new VorbisReader(resource.OpenStream());

            var channels   = reader.Channels;
            var sampleRate = reader.SampleRate;
            var seconds    = reader.TotalTime.TotalSeconds;
            var samples    = (int)Math.Ceiling(seconds * sampleRate * channels);

            var floats = new Span <float>(new float[samples]);

            if (reader.ReadSamples(floats) <= 0)
            {
                throw new Exception("Failed to read OGG stream.");
            }

            var shorts = new Span <short>(new short[samples]); // 16 bit

            for (var i = 0; i < floats.Length; i++)
                shorts[i] = (short)(short.MaxValue * floats[i]);

            fixed(void *p = &shorts.GetPinnableReference())
            {
                Al.BufferData(Buffer, channels == 2 ? Al.FormatStereo16 : Al.FormatMono16, p, shorts.Length * sizeof(short), sampleRate);
            }
        }
Пример #4
0
        public Sound(SoundManager owner, string filename, bool stream, bool streamsReliably, XElement xElement = null)
        {
            Owner           = owner;
            Filename        = Path.GetFullPath(filename.CleanUpPath()).CleanUpPath();
            Stream          = stream;
            StreamsReliably = streamsReliably;
            XElement        = xElement;

            BaseGain = 1.0f;
            BaseNear = 100.0f;
            BaseFar  = 200.0f;

            if (!stream)
            {
                Al.GenBuffer(out alBuffer);
                int alError = Al.GetError();
                if (alError != Al.NoError)
                {
                    throw new Exception("Failed to create OpenAL buffer for non-streamed sound: " + Al.GetErrorString(alError));
                }

                if (!Al.IsBuffer(alBuffer))
                {
                    throw new Exception("Generated OpenAL buffer is invalid!");
                }

                Al.GenBuffer(out alMuffledBuffer);
                alError = Al.GetError();
                if (alError != Al.NoError)
                {
                    throw new Exception("Failed to create OpenAL buffer for non-streamed sound: " + Al.GetErrorString(alError));
                }

                if (!Al.IsBuffer(alMuffledBuffer))
                {
                    throw new Exception("Generated OpenAL buffer is invalid!");
                }
            }
            else
            {
                alBuffer = 0;
            }
        }
Пример #5
0
        public SoundChannel(Sound sound, float gain, Vector3?position, float near, float far, string category, bool muffle = false)
        {
            Sound = sound;

            debugName = sound == null ?
                        "SoundChannel (null)" :
                        $"SoundChannel ({(string.IsNullOrEmpty(sound.Filename) ? "filename empty" : sound.Filename) })";

            IsStream         = sound.Stream;
            FilledByNetwork  = sound is VoipSound;
            decayTimer       = 0;
            streamSeekPos    = 0; reachedEndSample = false;
            buffersToRequeue = 4;
            muffled          = muffle;

            if (IsStream)
            {
                mutex = new object();
            }

            try
            {
                if (mutex != null)
                {
                    Monitor.Enter(mutex);
                }
                if (sound.Owner.CountPlayingInstances(sound) < sound.MaxSimultaneousInstances)
                {
                    ALSourceIndex = sound.Owner.AssignFreeSourceToChannel(this);
                }

                if (ALSourceIndex >= 0)
                {
                    if (!IsStream)
                    {
                        Al.Sourcei(sound.Owner.GetSourceFromIndex(Sound.SourcePoolIndex, ALSourceIndex), Al.Buffer, 0);
                        int alError = Al.GetError();
                        if (alError != Al.NoError)
                        {
                            throw new Exception("Failed to reset source buffer: " + debugName + ", " + Al.GetErrorString(alError));
                        }

                        if (!Al.IsBuffer(sound.ALBuffer))
                        {
                            throw new Exception(sound.Filename + " has an invalid buffer!");
                        }

                        uint alBuffer = sound.Owner.GetCategoryMuffle(category) || muffle ? sound.ALMuffledBuffer : sound.ALBuffer;
                        Al.Sourcei(sound.Owner.GetSourceFromIndex(Sound.SourcePoolIndex, ALSourceIndex), Al.Buffer, (int)alBuffer);
                        alError = Al.GetError();
                        if (alError != Al.NoError)
                        {
                            throw new Exception("Failed to bind buffer to source (" + ALSourceIndex.ToString() + ":" + sound.Owner.GetSourceFromIndex(Sound.SourcePoolIndex, ALSourceIndex) + "," + sound.ALBuffer.ToString() + "): " + debugName + ", " + Al.GetErrorString(alError));
                        }

                        Al.SourcePlay(sound.Owner.GetSourceFromIndex(Sound.SourcePoolIndex, ALSourceIndex));
                        alError = Al.GetError();
                        if (alError != Al.NoError)
                        {
                            throw new Exception("Failed to play source: " + debugName + ", " + Al.GetErrorString(alError));
                        }
                    }
                    else
                    {
                        uint alBuffer = sound.Owner.GetCategoryMuffle(category) || muffle ? sound.ALMuffledBuffer : sound.ALBuffer;
                        Al.Sourcei(sound.Owner.GetSourceFromIndex(Sound.SourcePoolIndex, ALSourceIndex), Al.Buffer, (int)alBuffer);
                        int alError = Al.GetError();
                        if (alError != Al.NoError)
                        {
                            throw new Exception("Failed to reset source buffer: " + debugName + ", " + Al.GetErrorString(alError));
                        }

                        Al.Sourcei(sound.Owner.GetSourceFromIndex(Sound.SourcePoolIndex, ALSourceIndex), Al.Looping, Al.False);
                        alError = Al.GetError();
                        if (alError != Al.NoError)
                        {
                            throw new Exception("Failed to set stream looping state: " + debugName + ", " + Al.GetErrorString(alError));
                        }

                        streamShortBuffer = new short[STREAM_BUFFER_SIZE];

                        streamBuffers          = new uint[4];
                        unqueuedBuffers        = new uint[4];
                        streamBufferAmplitudes = new float[4];
                        for (int i = 0; i < 4; i++)
                        {
                            Al.GenBuffer(out streamBuffers[i]);

                            alError = Al.GetError();
                            if (alError != Al.NoError)
                            {
                                throw new Exception("Failed to generate stream buffers: " + debugName + ", " + Al.GetErrorString(alError));
                            }

                            if (!Al.IsBuffer(streamBuffers[i]))
                            {
                                throw new Exception("Generated streamBuffer[" + i.ToString() + "] is invalid! " + debugName);
                            }
                        }
                        Sound.Owner.InitStreamThread();
                    }
                }

                this.Position = position;
                this.Gain     = gain;
                this.Looping  = false;
                this.Near     = near;
                this.Far      = far;
                this.Category = category;
            }
            catch
            {
                throw;
            }
            finally
            {
                if (mutex != null)
                {
                    Monitor.Exit(mutex);
                }
            }

            Sound.Owner.Update();
        }
Пример #6
0
        public SoundChannel(Sound sound, float gain, Vector3?position, float near, float far, string category, bool muffle = false)
        {
            Sound = sound;

            IsStream        = sound.Stream;
            FilledByNetwork = sound is VoipSound;
            decayTimer      = 0;
            streamSeekPos   = 0; reachedEndSample = false;
            startedPlaying  = true;

            mutex = new object();

            lock (mutex)
            {
                if (sound.Owner.CountPlayingInstances(sound) < sound.MaxSimultaneousInstances)
                {
                    ALSourceIndex = sound.Owner.AssignFreeSourceToChannel(this);
                }

                if (ALSourceIndex >= 0)
                {
                    if (!IsStream)
                    {
                        Al.Sourcei(sound.Owner.GetSourceFromIndex(Sound.SourcePoolIndex, ALSourceIndex), Al.Buffer, 0);
                        int alError = Al.GetError();
                        if (alError != Al.NoError)
                        {
                            throw new Exception("Failed to reset source buffer: " + Al.GetErrorString(alError));
                        }

                        if (!Al.IsBuffer(sound.ALBuffer))
                        {
                            throw new Exception(sound.Filename + " has an invalid buffer!");
                        }

                        uint alBuffer = sound.Owner.GetCategoryMuffle(category) || muffle ? sound.ALMuffledBuffer : sound.ALBuffer;
                        Al.Sourcei(sound.Owner.GetSourceFromIndex(Sound.SourcePoolIndex, ALSourceIndex), Al.Buffer, (int)alBuffer);
                        alError = Al.GetError();
                        if (alError != Al.NoError)
                        {
                            throw new Exception("Failed to bind buffer to source (" + ALSourceIndex.ToString() + ":" + sound.Owner.GetSourceFromIndex(Sound.SourcePoolIndex, ALSourceIndex) + "," + sound.ALBuffer.ToString() + "): " + Al.GetErrorString(alError));
                        }

                        Al.SourcePlay(sound.Owner.GetSourceFromIndex(Sound.SourcePoolIndex, ALSourceIndex));
                        alError = Al.GetError();
                        if (alError != Al.NoError)
                        {
                            throw new Exception("Failed to play source: " + Al.GetErrorString(alError));
                        }
                    }
                    else
                    {
                        Al.Sourcei(sound.Owner.GetSourceFromIndex(Sound.SourcePoolIndex, ALSourceIndex), Al.Buffer, (int)sound.ALBuffer);
                        int alError = Al.GetError();
                        if (alError != Al.NoError)
                        {
                            throw new Exception("Failed to reset source buffer: " + Al.GetErrorString(alError));
                        }

                        Al.Sourcei(sound.Owner.GetSourceFromIndex(Sound.SourcePoolIndex, ALSourceIndex), Al.Looping, Al.False);
                        alError = Al.GetError();
                        if (alError != Al.NoError)
                        {
                            throw new Exception("Failed to set stream looping state: " + Al.GetErrorString(alError));
                        }

                        streamShortBuffer = new short[STREAM_BUFFER_SIZE];

                        streamBuffers = new uint[4];
                        emptyBuffers  = new List <uint>();
                        for (int i = 0; i < 4; i++)
                        {
                            Al.GenBuffer(out streamBuffers[i]);

                            alError = Al.GetError();
                            if (alError != Al.NoError)
                            {
                                throw new Exception("Failed to generate stream buffers: " + Al.GetErrorString(alError));
                            }

                            if (!Al.IsBuffer(streamBuffers[i]))
                            {
                                throw new Exception("Generated streamBuffer[" + i.ToString() + "] is invalid!");
                            }
                        }

                        Sound.Owner.InitStreamThread();
                    }
                }

                this.Position = position;
                this.Gain     = gain;
                this.Looping  = false;
                this.Near     = near;
                this.Far      = far;
                this.Category = category;
            }
        }