Exemplo n.º 1
0
        /// <summary>
        /// Stop the <see cref="Sound"/>.
        /// </summary>
        public void Stop()
        {
            // This may cause OpenAL error if the Source is not valid.
            ALChecker.Check(() => AL.SourceStop(Source));
            Reader.DecodeTime = 0;

            if (!Deferred)
            {
                SoundSystem.Instance.RemoveUndeferredSource(Source);
                Deferred = true;
            }

            if (SoundStopped != null)
            {
                SoundStopped(this, EventArgs.Empty);
            }

            // In this case, we really need to check this first
            // Whether the Source is valid
            bool isValidSource = AL.IsSource(Source);

            ALChecker.CheckError();
            if (isValidSource)
            {
                // TODO: Should we really need to dispose the source here?
                ALChecker.Check(() => AL.DeleteSource(Source));
                Source = -1; // Set to invalid Source to make the next cycle source available
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Initialize the Native Handle, De-queue existing buffer and (re)Queue the buffer of the <see cref="SoundBuffer"/>.
        /// </summary>
        protected void Initialize()
        {
            // Check whether the buffer is already initializing state
            if (IsPreparing)
            {
                return;
            }

            // Check whether the current Source is valid
            bool isValidSource = AL.IsSource(Source);

            ALChecker.CheckError();
            if (!isValidSource || Source == -1)
            {
                // Get unused Source from SoundSystem
                Source = SoundSystem.Instance.GetAvailableSource();
            }

            // We don't have clue which buffer id that being attached to the source right now
            // So we don't attach (queue) the buffer to the source now
            // We will attach (queue) it when we are (really) going to queue the buffer (read: Play())

            // Initialize() call will dequeue current buffer and queue the buffer when its required

            // Check the sound state
            switch (State)
            {
            // Sound is already playing, no need preparation(?)
            case SoundState.Paused:
            case SoundState.Playing:
                return;

            // The sounds is already stopped (which mean its been played once or more before)
            case SoundState.Stopped:
                // Reset to 0 Position
                Reader.DecodeTime = 0;
                // Dequeue remaining buffer before we (re)queue the buffer
                DequeueBuffer();
                // We are not ready to start yet, we haven't queue the buffer
                IsReady = false;

                break;
            }

            // Check whether our buffer is ready
            if (!IsReady)
            {
                // If its not ready, lets queue them
                IsPreparing = true;  // set the flag to prevent requeue during process
                QueueBuffer(precache: true);
                IsPreparing = false; // done
            }
        }
Exemplo n.º 3
0
        internal int GetAvailableSource()
        {
            for (int i = 0; i < _sources.Length; i++)
            {
                bool isValidSource = AL.IsSource(_sources[i]);
                ALChecker.CheckError();

                if (isValidSource)
                {
                    // Some sources are probably used by another sounds
                    // Return the one that not in use

                    // Identify source state
                    ALSourceState state = AL.GetSourceState(_sources[i]);
                    ALChecker.CheckError();

                    // Do not use un-deferred source
                    if (_unDeferredSources.Contains(_sources[i]) && state == ALSourceState.Initial)
                    {
                        continue;
                    }
                    else if (_unDeferredSources.Contains(_sources[i]) && state == ALSourceState.Stopped)
                    {
                        _unDeferredSources.Remove(_sources[i]);
                    }

                    // No sounds using it or no longer in use, use it
                    if (state == ALSourceState.Initial || (state == ALSourceState.Stopped))
                    {
                        return(_sources[i]);
                    }
                    // Source is in use by a sound, find another one
                    else if (state == ALSourceState.Paused || state == ALSourceState.Playing)
                    {
                        continue;
                    }
                }
                else
                {
                    // Not a source (anymore..?)
                    // Generate and use it
                    _sources[i] = AL.GenSource();

                    // Since it's newly generated, it must be unused source
                    return(_sources[i]);
                }
            }

            // All sources are used at the moment...
            // Return invalid source
            return(-1);
        }
Exemplo n.º 4
0
        /// <summary>
        /// Initialize the <see cref="SoundSystem"/>.
        /// </summary>
        /// <param name="bufferSize"></param>
        public void Initialize(int bufferSize = DEFAULT_BUFFER_SIZE)
        {
            if (_context == null)
            {
                _context = new ALContext();
            }

            BufferSize = bufferSize;

            XRam = new XRamExtension();
            Efx  = new EffectsExtension();

            // Init empty sources
            _sources = AL.GenSources(MAXIMUM_NUMBER_OF_SOURCES);
            ALChecker.CheckError();
        }
Exemplo n.º 5
0
        /// <summary>
        /// Update the <see cref="SoundSystem"/>.
        /// </summary>
        /// <param name="delta"></param>
        public void Update(double delta)
        {
            // Copy to a new list
            List <SoundBuffer> soundStreams = new List <SoundBuffer>(_sounds);

            // Loop it
            foreach (var sound in soundStreams)
            {
                // The sounds is no longer exist, skip it
                if (!_sounds.Contains(sound))
                {
                    continue;
                }

                bool finished = false;

                // Get how many queued buffers
                int queued = -1;
                ALChecker.Check(() => AL.GetSource(sound.Source, ALGetSourcei.BuffersQueued, out queued));

                // Get how many processed buffers
                int processed = -1;
                ALChecker.Check(() => AL.GetSource(sound.Source, ALGetSourcei.BuffersProcessed, out processed));

                // Every queued buffers are processed, skip it
                if (processed == 0 && queued == sound.Buffers.Length)
                {
                    continue;
                }

                // Unqueue the processed buffers
                int[] tempBuffers;
                if (processed > 0)
                {
                    tempBuffers = AL.SourceUnqueueBuffers(sound.Source, processed);
                    ALChecker.CheckError();
                }
                else
                {
                    // Get remaining queued buffers
                    List <int> buffers = new List <int>();
                    for (int i = queued; i < sound.Buffers.Length; i++)
                    {
                        buffers.Add(sound.Buffers[i]);
                    }

                    //tempBuffers = sound.alBufferIds.Skip(queued).ToArray();
                    tempBuffers = buffers.ToArray();
                }

                // Loop for each queued buffers
                for (int i = 0; i < tempBuffers.Length; i++)
                {
                    // Upload buffer data of samples and check whether its already processed
                    finished |= sound.Reader.BufferData(BufferSize, tempBuffers[i]);

                    // Buffer data has been processed
                    if (finished)
                    {
                        // Check whether the sounds is looping
                        // Reset position of DecodeTime to zero
                        // Since Looping via AL command is not supported on stream sounds.
                        if (sound.IsLooping)
                        {
                            sound.Reader.DecodeTime = 0;
                        }
                        else
                        {
                            // No repeat, then safely remove the sounds from the queue list
                            // Triger the event first before remove
                            sound.OnFinish();

                            _sounds.Remove(sound);
                            i = tempBuffers.Length;
                        }
                    }
                }

                ALChecker.Check(() => AL.SourceQueueBuffers(sound.Source, tempBuffers.Length, tempBuffers));

                if (finished && !sound.IsLooping)
                {
                    continue;
                }

                if (sound.IsPreparing)
                {
                    continue;
                }

                if (!_sounds.Contains(sound))
                {
                    continue;
                }

                var state = AL.GetSourceState(sound.Source);
                ALChecker.CheckError();
                if (state == ALSourceState.Stopped)
                {
                    ALChecker.Check(() => AL.SourcePlay(sound.Source));
                }
            }
        }