Ejemplo n.º 1
0
 /// <summary>
 /// Get the number of processed buffers.
 /// </summary>
 public int ProcessedBuffers()
 {
     CheckDisposed();
     Context.MakeCurrent();
     AL10.alGetSourcei(Name, AL10.AL_BUFFERS_PROCESSED, out var processed);
     AlHelper.AlCheckError("Failed to get number of processed buffers.");
     return(processed);
 }
Ejemplo n.º 2
0
 protected void StopSource()
 {
     AL10.alGetSourcei(Source, AL10.AL_SOURCE_STATE, out var state);
     if (state == AL10.AL_PLAYING || state == AL10.AL_PAUSED)
     {
         AL10.alSourceStop(Source);
     }
 }
Ejemplo n.º 3
0
        internal bool Update()
        {
            if (State == SoundState.Stopped)
            {
                /* If we've stopped, remove ourselves from the list.
                 * Do NOT do anything else, Play/Stop/Dispose do this!
                 * -flibit
                 */
                return(false);
            }

            // Get the processed buffers.
            int finishedBuffers;

            AL10.alGetSourcei(
                INTERNAL_alSource,
                AL10.AL_BUFFERS_PROCESSED,
                out finishedBuffers
                );
            if (finishedBuffers == 0)
            {
                // Nothing to do... yet.
                return(true);
            }

            uint[] bufs = new uint[finishedBuffers];
            AL10.alSourceUnqueueBuffers(
                INTERNAL_alSource,
                (IntPtr)finishedBuffers,
                bufs
                );
            PendingBufferCount -= finishedBuffers;
            if (BufferNeeded != null)
            {
                // PendingBufferCount changed during playback, trigger now!
                BufferNeeded(this, null);
            }

            // Error check our queuedBuffers list.
            for (int i = 0; i < finishedBuffers; i += 1)
            {
                uint newBuf = queuedBuffers.Dequeue();
                if (newBuf != bufs[i])
                {
                    throw new Exception("Buffer desync!");
                }
                availableBuffers.Enqueue(newBuf);
            }

            // Notify the application that we need moar buffers!
            if (PendingBufferCount <= 2 && BufferNeeded != null)
            {
                BufferNeeded(this, null);
            }

            return(true);
        }
Ejemplo n.º 4
0
        public int CheckProcessedBuffers(IALSource source)
        {
            int result;

            AL10.alGetSourcei(
                (source as OpenALSource).Handle,
                AL10.AL_BUFFERS_PROCESSED,
                out result
                );
            return(result);
        }
Ejemplo n.º 5
0
 public void StopAllSounds()
 {
     foreach (var key in sourcePool.Keys)
     {
         int state;
         AL10.alGetSourcei(key, AL10.AL_SOURCE_STATE, out state);
         if (state == AL10.AL_PLAYING || state == AL10.AL_PAUSED)
         {
             AL10.alSourceStop(key);
         }
     }
 }
Ejemplo n.º 6
0
        private void alSourcePlay()
        {
            int state = AL10.alGetSourcei(alSource, AL10.AL_SOURCE_STATE);

            if (state != AL10.AL_PLAYING)
            {
                if (minimumNumberBuffers <= 0 || WaitingBuffers >= minimumNumberBuffers)
                {
                    AL10.alSourcePlay(alSource);
                }
            }
        }
Ejemplo n.º 7
0
        public int CheckProcessedBuffers(IALSource source)
        {
            int result;

            AL10.alGetSourcei(
                (source as OpenALSource).Handle,
                AL10.AL_BUFFERS_PROCESSED,
                out result
                );
#if VERBOSE_AL_DEBUGGING
            CheckALError();
#endif
            return(result);
        }
Ejemplo n.º 8
0
        public void SetSoundVolume(float volume, ISound music, ISound video)
        {
            var sounds = sourcePool.Keys.Where(key =>
            {
                AL10.alGetSourcei(key, AL10.AL_SOURCE_STATE, out var state);
                return((state == AL10.AL_PLAYING || state == AL10.AL_PAUSED) &&
                       (music == null || key != ((OpenAlSound)music).Source) &&
                       (video == null || key != ((OpenAlSound)video).Source));
            });

            foreach (var s in sounds)
            {
                AL10.alSourcef(s, AL10.AL_GAIN, volume);
            }
        }
Ejemplo n.º 9
0
        public void StopSound(ISound sound)
        {
            if (sound == null)
            {
                return;
            }

            var key = ((OpenAlSound)sound).Source;
            int state;

            AL10.alGetSourcei(key, AL10.AL_SOURCE_STATE, out state);
            if (state == AL10.AL_PLAYING || state == AL10.AL_PAUSED)
            {
                AL10.alSourceStop(key);
            }
        }
Ejemplo n.º 10
0
 public void SetAllSoundsPaused(bool paused)
 {
     foreach (var key in sourcePool.Keys)
     {
         int state;
         AL10.alGetSourcei(key, AL10.AL_SOURCE_STATE, out state);
         if (state == AL10.AL_PLAYING && paused)
         {
             AL10.alSourcePause(key);
         }
         else if (state == AL10.AL_PAUSED && !paused)
         {
             AL10.alSourcePlay(key);
         }
     }
 }
Ejemplo n.º 11
0
 public virtual void checkFreeBuffers(int alSource)
 {
     while (true)
     {
         int processedBuffers = AL10.alGetSourcei(alSource, AL10.AL_BUFFERS_PROCESSED);
         if (processedBuffers <= 0)
         {
             break;
         }
         int alBuffer = AL10.alSourceUnqueueBuffers(alSource);
         //if (log.DebugEnabled)
         {
             Console.WriteLine(string.Format("free buffer {0:D}", alBuffer));
         }
         freeBuffers.Push(alBuffer);
     }
 }
Ejemplo n.º 12
0
        public SoundState GetSourceState(IALSource source)
        {
            int state;

            AL10.alGetSourcei(
                (source as OpenALSource).Handle,
                AL10.AL_SOURCE_STATE,
                out state
                );
            if (state == AL10.AL_PLAYING)
            {
                return(SoundState.Playing);
            }
            else if (state == AL10.AL_PAUSED)
            {
                return(SoundState.Paused);
            }
            return(SoundState.Stopped);
        }
Ejemplo n.º 13
0
        public void PauseSound(ISound sound, bool paused)
        {
            if (sound == null)
            {
                return;
            }

            var key = ((OpenAlSound)sound).Source;
            int state;

            AL10.alGetSourcei(key, AL10.AL_SOURCE_STATE, out state);
            if (state == AL10.AL_PLAYING && paused)
            {
                AL10.alSourcePause(key);
            }
            else if (state == AL10.AL_PAUSED && !paused)
            {
                AL10.alSourcePlay(key);
            }
        }
Ejemplo n.º 14
0
        bool TryGetSourceFromPool(out uint source)
        {
            foreach (var kvp in sourcePool)
            {
                if (!kvp.Value.IsActive)
                {
                    sourcePool[kvp.Key].IsActive = true;
                    source = kvp.Key;
                    return(true);
                }
            }

            var freeSources = new List <uint>();

            foreach (var key in sourcePool.Keys)
            {
                int state;
                AL10.alGetSourcei(key, AL10.AL_SOURCE_STATE, out state);
                if (state != AL10.AL_PLAYING && state != AL10.AL_PAUSED)
                {
                    freeSources.Add(key);
                }
            }

            if (freeSources.Count == 0)
            {
                source = 0;
                return(false);
            }

            foreach (var i in freeSources)
            {
                sourcePool[i].IsActive = false;
            }

            sourcePool[freeSources[0]].IsActive = true;

            source = freeSources[0];
            return(true);
        }
Ejemplo n.º 15
0
        public SoundState GetSourceState(IALSource source)
        {
            int state;

            AL10.alGetSourcei(
                (source as OpenALSource).Handle,
                AL10.AL_SOURCE_STATE,
                out state
                );
#if VERBOSE_AL_DEBUGGING
            CheckALError();
#endif
            if (state == AL10.AL_PLAYING)
            {
                return(SoundState.Playing);
            }
            else if (state == AL10.AL_PAUSED)
            {
                return(SoundState.Paused);
            }
            return(SoundState.Stopped);
        }
Ejemplo n.º 16
0
 void PauseSound(uint source, bool paused)
 {
     AL10.alGetSourcei(source, AL10.AL_SOURCE_STATE, out var state);
     if (paused)
     {
         if (state == AL10.AL_PLAYING)
         {
             AL10.alSourcePause(source);
         }
         else if (state == AL10.AL_INITIAL)
         {
             // If a sound hasn't started yet,
             // we indicate it should not play be transitioning it to the stopped state.
             AL10.alSourcePlay(source);
             AL10.alSourceStop(source);
         }
     }
     else if (!paused && state != AL10.AL_PLAYING)
     {
         AL10.alSourcePlay(source);
     }
 }
Ejemplo n.º 17
0
        public void GetBufferData(
            IALSource source,
            IALBuffer[] buffer,
            IntPtr samples,
            int samplesLen,
            AudioChannels channels
            )
        {
            int copySize1 = samplesLen / (int)channels;
            int copySize2 = 0;

            // Where are we now?
            int offset;

            AL10.alGetSourcei(
                (source as OpenALSource).Handle,
                AL11.AL_SAMPLE_OFFSET,
                out offset
                );

            // Is that longer than what the active buffer has left...?
            uint buf = (buffer[0] as OpenALBuffer).Handle;
            int  len;

            AL10.alGetBufferi(
                buf,
                AL10.AL_SIZE,
                out len
                );
            len /= 2;             // FIXME: Assuming 16-bit!
            len /= (int)channels;
            if (offset > len)
            {
                copySize2 = copySize1;
                copySize1 = 0;
                offset   -= len;
            }
            else if (offset + copySize1 > len)
            {
                copySize2 = copySize1 - (len - offset);
                copySize1 = (len - offset);
            }

            // Copy!
            if (copySize1 > 0)
            {
                ALEXT.alGetBufferSamplesSOFT(
                    buf,
                    offset,
                    copySize1,
                    channels == AudioChannels.Stereo ?
                    ALEXT.AL_STEREO_SOFT :
                    ALEXT.AL_MONO_SOFT,
                    ALEXT.AL_FLOAT_SOFT,
                    samples
                    );
                offset = 0;
            }
            if (buffer.Length > 1 && copySize2 > 0)
            {
                ALEXT.alGetBufferSamplesSOFT(
                    (buffer[1] as OpenALBuffer).Handle,
                    0,
                    copySize2,
                    channels == AudioChannels.Stereo ?
                    ALEXT.AL_STEREO_SOFT :
                    ALEXT.AL_MONO_SOFT,
                    ALEXT.AL_FLOAT_SOFT,
                    samples + (copySize1 * (int)channels)
                    );
            }
        }
Ejemplo n.º 18
0
        public OpenAlAsyncLoadSound(uint source, bool looping, bool relative, WPos pos, float volume, int channels, int sampleBits, int sampleRate, Stream stream)
            : base(source, looping, relative, pos, volume, sampleRate)
        {
            // Load a silent buffer into the source. Without this,
            // attempting to change the state (i.e. play/pause) the source fails on some systems.
            var silentSource = new OpenAlSoundSource(SilentData, SilentData.Length, channels, sampleBits, sampleRate);

            AL10.alSourcei(source, AL10.AL_BUFFER, (int)silentSource.Buffer);

            playTask = Task.Run(async() =>
            {
                MemoryStream memoryStream;
                using (stream)
                {
                    try
                    {
                        memoryStream = new MemoryStream((int)stream.Length);
                    }
                    catch (NotSupportedException)
                    {
                        // Fallback for stream types that don't support Length.
                        memoryStream = new MemoryStream();
                    }

                    try
                    {
                        await stream.CopyToAsync(memoryStream, 81920, cts.Token);
                    }
                    catch (TaskCanceledException)
                    {
                        // Sound was stopped early, cleanup the unused buffer and exit.
                        AL10.alSourceStop(source);
                        AL10.alSourcei(source, AL10.AL_BUFFER, 0);
                        silentSource.Dispose();
                        return;
                    }
                }

                var data           = memoryStream.GetBuffer();
                var dataLength     = (int)memoryStream.Length;
                var bytesPerSample = sampleBits / 8f;
                var lengthInSecs   = dataLength / (channels * bytesPerSample * sampleRate);
                using (var soundSource = new OpenAlSoundSource(data, dataLength, channels, sampleBits, sampleRate))
                {
                    // Need to stop the source, before attaching the real input and deleting the silent one.
                    AL10.alSourceStop(source);
                    AL10.alSourcei(source, AL10.AL_BUFFER, (int)soundSource.Buffer);
                    silentSource.Dispose();

                    lock (cts)
                    {
                        if (!cts.IsCancellationRequested)
                        {
                            // TODO: A race condition can happen between the state check and playing/rewinding if a
                            // user pauses/resumes at the right moment. The window of opportunity is small and the
                            // consequences are minor, so for now we'll ignore it.
                            int state;
                            AL10.alGetSourcei(Source, AL10.AL_SOURCE_STATE, out state);
                            if (state != AL10.AL_STOPPED)
                            {
                                AL10.alSourcePlay(source);
                            }
                            else
                            {
                                // A stopped sound indicates it was paused before we finishing loaded.
                                // We don't want to start playing it right away.
                                // We rewind the source so when it is started, it plays from the beginning.
                                AL10.alSourceRewind(source);
                            }
                        }
                    }

                    while (!cts.IsCancellationRequested)
                    {
                        // Need to check seek before state. Otherwise, the music can stop after our state check at
                        // which point the seek will be zero, meaning we'll wait the full track length before seeing it
                        // has stopped.
                        var currentSeek = SeekPosition;

                        int state;
                        AL10.alGetSourcei(Source, AL10.AL_SOURCE_STATE, out state);
                        if (state == AL10.AL_STOPPED)
                        {
                            break;
                        }

                        try
                        {
                            // Wait until the track is due to complete, and at most 60 times a second to prevent a
                            // busy-wait.
                            var delaySecs = Math.Max(lengthInSecs - currentSeek, 1 / 60f);
                            await Task.Delay(TimeSpan.FromSeconds(delaySecs), cts.Token);
                        }
                        catch (TaskCanceledException)
                        {
                            // Sound was stopped early, allow normal cleanup to occur.
                        }
                    }

                    AL10.alSourcei(Source, AL10.AL_BUFFER, 0);
                }
            });
        }