예제 #1
0
        public void Dispose()
        {
            if (this.IsDisposed)
            {
                return;
            }
            this.IsDisposed = true;
            ALSourceState sourceState = AL.GetSourceState(this.alSourceId);

            if (sourceState == ALSourceState.Playing || sourceState == ALSourceState.Paused)
            {
                this.StopPlayback();
            }
            lock (this.prepareMutex)
            {
                if (OggStreamer.HasInstance)
                {
                    OggStreamer.Instance.RemoveStream(this);
                }
                if (sourceState != ALSourceState.Initial)
                {
                    this.Empty(false);
                }
                this.Close();
                this.underlyingStream.Dispose();
            }
            if (OpenALSoundController.Instance != null)
            {
                OpenALSoundController.Instance.ReturnSource(this.alSourceId);
                OpenALSoundController.Instance.ReturnBuffers(this.alBufferIds);
            }
            ALHelper.Check();
        }
예제 #2
0
        public void Prepare(bool asynchronous = false)
        {
            ALSourceState sourceState = AL.GetSourceState(this.alSourceId);

            lock (this.stopMutex)
            {
                switch (sourceState)
                {
                case ALSourceState.Playing:
                    break;

                case ALSourceState.Paused:
                    break;

                default:
                    lock (this.prepareMutex)
                    {
                        if (this.Reader == null)
                        {
                            this.Open();
                        }
                        if (!this.Precaching)
                        {
                            this.Precaching = true;
                            this.Precache(asynchronous);
                            break;
                        }
                        else
                        {
                            break;
                        }
                    }
                }
            }
        }
예제 #3
0
        public void Prepare(bool asynchronous = false)
        {
            ALSourceState sourceState = AL.GetSourceState(this.alSourceId);

            this.StoppingLock.EnterReadLock();
            switch (sourceState)
            {
            case ALSourceState.Playing:
            case ALSourceState.Paused:
                this.StoppingLock.ExitReadLock();
                break;

            default:
                this.PreparationLock.EnterWriteLock();
                if (this.Reader == null)
                {
                    this.Open();
                }
                if (!this.Precaching)
                {
                    this.Precaching = true;
                    this.Precache(asynchronous);
                }
                this.PreparationLock.ExitWriteLock();
                this.StoppingLock.ExitReadLock();
                break;
            }
        }
예제 #4
0
 public void Play(int Source)
 {
     Stop();
     this.Source = Source;
     AL.Source(Source, ALSourcei.Buffer, Buffer);
     AL.SourcePlay(Source);
     SourceState = AL.GetSourceState(Source);
 }
예제 #5
0
파일: Audio.cs 프로젝트: meatRay/Gale
        public async Task Play()
        {
            AL.SourcePlay(_source);
            do
            {
                await Task.Delay(100);

                State = AL.GetSourceState(_source);
            } while (State == ALSourceState.Playing);
            AL.SourceStop(_source);
        }
예제 #6
0
        private void StartPlaybackIfNeeded(Track Td)
        {
            AL.GetSource(Td.SourceId, ALGetSourcei.SourceState, out int StateInt);

            ALSourceState State = (ALSourceState)StateInt;

            if (State != ALSourceState.Playing && Td.State == PlaybackState.Playing)
            {
                AL.SourcePlay(Td.SourceId);
            }
        }
예제 #7
0
        private void StartIfNotPlaying()
        {
            AL.GetSource(_sourceId, ALGetSourcei.SourceState, out int stateInt);

            ALSourceState State = (ALSourceState)stateInt;

            if (State != ALSourceState.Playing)
            {
                AL.SourcePlay(_sourceId);
            }
        }
예제 #8
0
        private void StartPlaybackIfNeeded(OpenALAudioTrack track)
        {
            AL.GetSource(track.SourceId, ALGetSourcei.SourceState, out int stateInt);

            ALSourceState State = (ALSourceState)stateInt;

            if (State != ALSourceState.Playing && track.State == PlaybackState.Playing)
            {
                AL.SourcePlay(track.SourceId);
            }
        }
예제 #9
0
        private void Play()
        {
            AL.GetSource(Source, ALGetSourcei.SourceState, out int state);

            ALSourceState actualState = (ALSourceState)state;

            if (actualState != ALSourceState.Playing)
            {
                AL.SourcePlay(Source);
            }
        }
예제 #10
0
        void INativeAudioSource.ApplyState(ref AudioSourceState state)
        {
            lock (this.strLock)
            {
                ALSourceState nativeState = AL.GetSourceState(this.handle);
                bool          looped      = state.Looped && !this.isStreamed;

                if (this.isFirstUpdate || this.lastState.RelativeToListener != state.RelativeToListener)
                {
                    AL.Source(handle, ALSourceb.SourceRelative, state.RelativeToListener);
                }
                if (this.isFirstUpdate || this.lastState.Position != state.Position)
                {
                    AL.Source(handle, ALSource3f.Position, state.Position.X, -state.Position.Y, -state.Position.Z * 0.5f);
                }
                if (this.isFirstUpdate || this.lastState.Velocity != state.Velocity)
                {
                    AL.Source(handle, ALSource3f.Velocity, state.Velocity.X, -state.Velocity.Y, -state.Velocity.Z);
                }
                if (this.isFirstUpdate || this.lastState.MaxDistance != state.MaxDistance)
                {
                    AL.Source(handle, ALSourcef.MaxDistance, state.MaxDistance);
                }
                if (this.isFirstUpdate || this.lastState.MinDistance != state.MinDistance)
                {
                    AL.Source(handle, ALSourcef.ReferenceDistance, state.MinDistance);
                }
                if (this.isFirstUpdate || this.lastState.Looped != looped)
                {
                    AL.Source(handle, ALSourceb.Looping, looped);
                }
                if (this.isFirstUpdate || this.lastState.Volume != state.Volume)
                {
                    AL.Source(handle, ALSourcef.Gain, state.Volume);
                }
                if (this.isFirstUpdate || this.lastState.Pitch != state.Pitch)
                {
                    AL.Source(handle, ALSourcef.Pitch, state.Pitch);
                }

                if (state.Paused && nativeState == ALSourceState.Playing)
                {
                    AL.SourcePause(handle);
                }
                else if (!state.Paused && nativeState == ALSourceState.Paused)
                {
                    AL.SourcePlay(handle);
                }

                this.lastState        = state;
                this.lastState.Looped = looped;
                this.isFirstUpdate    = false;
            }
        }
예제 #11
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);
        }
예제 #12
0
        private static ChannelState ALSourceStateToChannelState(ALSourceState alSourceState)
        {
            switch (alSourceState)
            {
            case ALSourceState.Playing:
                return(ChannelState.Playing);

            case ALSourceState.Paused:
                return(ChannelState.Paused);

            default:
                return(ChannelState.Stopped);
            }
        }
예제 #13
0
        internal bool PerformStreaming()
        {
            lock (this.strLock)
            {
                if (this.handle == 0)
                {
                    return(false);
                }

                ALSourceState stateTemp = AL.GetSourceState(this.handle);
                if ((stateTemp == ALSourceState.Stopped || stateTemp == ALSourceState.Initial) && this.strStopReq != StopRequest.None)
                {
                    // Stopped due to regular EOF. If strStopReq is NOT set,
                    // the source stopped playing because it reached the end of the buffer
                    // but in fact only because we were too slow inserting new data.
                    // When stream is empty, source is still in initial state but strStopReq
                    // is already set to EndOfStream.
                    return(false);
                }
                else if (this.strStopReq == StopRequest.Immediately)
                {
                    // Stopped intentionally due to Stop()
                    AL.SourceStop(handle);
                    return(false);
                }

                if (stateTemp == ALSourceState.Initial)
                {
                    // Initialize streaming
                    PerformStreamingBegin();

                    // Initially play source
                    AL.SourcePlay(handle);
                }
                else
                {
                    // Stream new data
                    PerformStreamingUpdate();

                    // If the source stopped unintentionally, restart it. (See above)
                    if (stateTemp == ALSourceState.Stopped && this.strStopReq == StopRequest.None)
                    {
                        AL.SourcePlay(handle);
                    }
                }
            }

            return(true);
        }
예제 #14
0
        public void Stop()
        {
            ALSourceState sourceState = AL.GetSourceState(this.alSourceId);

            if (sourceState == ALSourceState.Playing || sourceState == ALSourceState.Paused)
            {
                this.StopPlayback();
            }
            lock (this.stopMutex)
            {
                if (!OggStreamer.HasInstance)
                {
                    return;
                }
                OggStreamer.Instance.RemoveStream(this);
            }
        }
예제 #15
0
        private void StartPlaybackIfNeeded(OpenALAudioTrack track)
        {
            AL.GetSource(track.SourceId, ALGetSourcei.SourceState, out int stateInt);

            ALSourceState State = (ALSourceState)stateInt;

            if (State != ALSourceState.Playing && track.State == PlaybackState.Playing)
            {
                if (_volumeChanged)
                {
                    AL.Source(track.SourceId, ALSourcef.Gain, _volume);

                    _volumeChanged = false;
                }

                AL.SourcePlay(track.SourceId);
            }
        }
예제 #16
0
        public int CalculateSamplesNeeded()
        {
            int           currentSamplesPlayed = GetSource(ALGetSourcei.SampleOffset);
            ALSourceState sourceState          = AL.GetSourceState(_sourceID);
            bool          isInitializing       = sourceState == ALSourceState.Initial;
            bool          detectedUnderrun     = sourceState == ALSourceState.Stopped;

            if (detectedUnderrun)
            {
                // SampleOffset should reset to 0 when stopped; update the queued sample count to match
                UnqueueProcessedBuffers();
                currentSamplesPlayed = 0;
            }
            int samplesAwaitingPlayback = _currentSamplesQueued - currentSamplesPlayed;
            int samplesNeeded           = Math.Max(BufferSizeSamples - samplesAwaitingPlayback, 0);

            if (isInitializing || detectedUnderrun)
            {
                _sound.HandleInitializationOrUnderrun(detectedUnderrun, ref samplesNeeded);
            }
            return(samplesNeeded);
        }
예제 #17
0
		public void Pause () {
			_userState = ALSourceState.Paused;
			while (AL.GetSourceState(_source) != ALSourceState.Paused)
				Thread.Sleep(1);
		}
예제 #18
0
		public void Stop () {
			_userState = ALSourceState.Stopped;
			while (AL.GetSourceState(_source) != ALSourceState.Stopped && AL.GetSourceState(_source) != ALSourceState.Initial)
				Thread.Sleep(1);
		}
예제 #19
0
        public void Update(double time)
        {
            updateTime += time;

            if (updateTime >= .25)
            {
                State = AL.GetSourceState(SourceID);
            }

            if (Looping && State == ALSourceState.Stopped)
            {
                Stop();
                Play();
            }
        }
예제 #20
0
        internal bool PerformStreaming()
        {
            lock (this.strLock)
            {
                if (this.Disposed)
                {
                    return(false);
                }
                if (!DualityApp.Sound.IsAvailable)
                {
                    return(false);
                }

                ALSourceState stateTemp       = ALSourceState.Stopped;
                bool          sourceAvailable = this.alSource > AlSource_NotAvailable;
                if (sourceAvailable)
                {
                    stateTemp = AL.GetSourceState(this.alSource);
                }

                if (stateTemp == ALSourceState.Stopped && this.strStopReq != StopRequest.None)
                {
                    // Stopped due to regular EOF. If strStopReq is NOT set,
                    // the source stopped playing because it reached the end of the buffer
                    // but in fact only because we were too slow inserting new data.
                    return(false);
                }
                else if (this.strStopReq == StopRequest.Immediately)
                {
                    // Stopped intentionally due to Stop()
                    if (this.alSource > AlSource_NotAvailable)
                    {
                        AL.SourceStop(this.alSource);
                    }
                    return(false);
                }

                AudioData audioDataRes = this.audioData.Res;
                if (!this.sound.IsAvailable || audioDataRes == null)
                {
                    this.Dispose();
                    return(false);
                }

                if (sourceAvailable)
                {
                    if (stateTemp == ALSourceState.Initial)
                    {
                        // Initialize streaming
                        PerformStreamingBegin(audioDataRes);

                        // Initially play source
                        AL.SourcePlay(this.alSource);
                        stateTemp = AL.GetSourceState(this.alSource);
                    }
                    else
                    {
                        // Stream new data
                        PerformStreamingUpdate(audioDataRes);

                        // If the source stopped unintentionally, restart it. (See above)
                        if (stateTemp == ALSourceState.Stopped && this.strStopReq == StopRequest.None)
                        {
                            AL.SourcePlay(this.alSource);
                        }
                    }
                }
            }

            return(true);
        }
예제 #21
0
        public bool IsPaused()
        {
            ALSourceState state = AL.GetSourceState(mySource);

            return(state == ALSourceState.Paused);
        }
예제 #22
0
        void INativeAudioSource.ApplyState(ref AudioSourceState state)
        {
            lock (this.strLock)
            {
                ALSourceState nativeState = AL.GetSourceState(this.handle);
                bool          looped      = state.Looped && !this.isStreamed;

                if (this.isFirstUpdate || this.lastState.RelativeToListener != state.RelativeToListener)
                {
                    AL.Source(handle, ALSourceb.SourceRelative, state.RelativeToListener);
                }
                if (this.isFirstUpdate || this.lastState.Position != state.Position)
                {
                    AL.Source(handle, ALSource3f.Position, state.Position.X, -state.Position.Y, -state.Position.Z * 0.5f);
                }
                if (this.isFirstUpdate || this.lastState.Velocity != state.Velocity)
                {
                    AL.Source(handle, ALSource3f.Velocity, state.Velocity.X, -state.Velocity.Y, -state.Velocity.Z);
                }
                if (this.isFirstUpdate || this.lastState.MaxDistance != state.MaxDistance)
                {
                    AL.Source(handle, ALSourcef.MaxDistance, state.MaxDistance);
                }
                if (this.isFirstUpdate || this.lastState.MinDistance != state.MinDistance)
                {
                    AL.Source(handle, ALSourcef.ReferenceDistance, state.MinDistance);
                }
                if (this.isFirstUpdate || this.lastState.Looped != looped)
                {
                    AL.Source(handle, ALSourceb.Looping, looped);
                }
                if (this.isFirstUpdate || this.lastState.Volume != state.Volume)
                {
                    AL.Source(handle, ALSourcef.Gain, state.Volume);
                }
                if (this.isFirstUpdate || this.lastState.Pitch != state.Pitch)
                {
                    AL.Source(handle, ALSourcef.Pitch, state.Pitch);
                }

                // Update lowpass settings requires Effects extension
                if (this.isFirstUpdate || this.lastState.Lowpass != state.Lowpass)
                {
                    var fx = AudioBackend.ActiveInstance.EffectsExtension;
                    if (fx != null)
                    {
                        // If there is no filter, create one when required.
                        if (this.filterHandle == 0 && state.Lowpass < 1.0f)
                        {
                            this.filterHandle = fx.GenFilter();
                            fx.Filter(this.filterHandle, EfxFilteri.FilterType, (int)EfxFilterType.Lowpass);
                            fx.Filter(this.filterHandle, EfxFilterf.LowpassGain, 1);
                        }
                        // If there is a filter, keep it up-to-date
                        if (this.filterHandle != 0)
                        {
                            fx.Filter(this.filterHandle, EfxFilterf.LowpassGainHF, MathF.Clamp(state.Lowpass, 0.0f, 1.0f));
                            fx.BindFilterToSource(this.handle, this.filterHandle);
                        }
                    }
                }

                if (state.Paused && nativeState == ALSourceState.Playing)
                {
                    AL.SourcePause(handle);
                }
                else if (!state.Paused && nativeState == ALSourceState.Paused)
                {
                    AL.SourcePlay(handle);
                }

                this.lastState        = state;
                this.lastState.Looped = looped;
                this.isFirstUpdate    = false;
            }
        }
예제 #23
0
파일: Audio.cs 프로젝트: meatRay/Gale
 public Audio(int source, int buffer)
 {
     _source = source;
     _buffer = buffer;
     State   = ALSourceState.Initial;
 }
예제 #24
0
 public void Playing_ShouldBeFalse_OnNonPlayingStates(ALSourceState state)
 {
     adapter.Setup(a => a.GetSourceState(sound.SourceHandle))
            .Returns(state);
     sound.Playing.ShouldBeFalse();
 }
예제 #25
0
 public void Stopped_ReturnsFalse_OnNonStoppedStates(ALSourceState state)
 {
     adapter.Setup(a => a.GetSourceState(sound.SourceHandle))
            .Returns(state);
     sound.Stopped.ShouldBeFalse();
 }
예제 #26
0
        private static void ThreadStreamFunc(object param)
        {
            SoundInstance sndInst = (SoundInstance)param;

            while (true)
            {
                lock (sndInst.strLock)
                {
                    if (sndInst.Disposed)
                    {
                        return;
                    }
                    if (!DualityApp.Sound.IsAvailable)
                    {
                        return;
                    }

                    ALSourceState stateTemp = ALSourceState.Stopped;
                    if (sndInst.alSource > AlSource_NotAvailable)
                    {
                        stateTemp = AL.GetSourceState(sndInst.alSource);
                    }

                    if (sndInst.strStopReq)
                    {
                        // Stopped intentionally due to Stop() or eof. If strStopReq is NOT set,
                        // the source stopped playing because it reached the end of the buffer
                        // but in fact only because we were too slow inserting new data.
                        if (stateTemp != ALSourceState.Stopped)
                        {
                            sndInst.Stop();
                        }
                        return;
                    }

                    Sound res = sndInst.snd.Res;
                    if (res == null)
                    {
                        sndInst.Dispose();
                        return;
                    }
                    if (stateTemp == ALSourceState.Initial)
                    {
                        // Generate streaming buffers
                        sndInst.strAlBuffers = new int[3];
                        for (int i = 0; i < sndInst.strAlBuffers.Length; ++i)
                        {
                            AL.GenBuffers(1, out sndInst.strAlBuffers[i]);
                        }

                        // Begin streaming
                        OV.BeginStreamFromMemory(res.Data.Res.OggVorbisData, out sndInst.strOvStr);

                        // Initially, completely fill all buffers
                        for (int i = 0; i < sndInst.strAlBuffers.Length; ++i)
                        {
                            PcmData pcm;
                            bool    eof = !OV.StreamChunk(sndInst.strOvStr, out pcm);
                            if (pcm.data.Length > 0)
                            {
                                AL.BufferData(
                                    sndInst.strAlBuffers[i],
                                    pcm.channelCount == 1 ? ALFormat.Mono16 : ALFormat.Stereo16,
                                    pcm.data,
                                    pcm.data.Length,
                                    pcm.sampleRate);
                                AL.SourceQueueBuffer(sndInst.alSource, sndInst.strAlBuffers[i]);
                                if (eof)
                                {
                                    break;
                                }
                            }
                            else
                            {
                                break;
                            }
                        }

                        // Initially play source
                        AL.SourcePlay(sndInst.alSource);
                        stateTemp = AL.GetSourceState(sndInst.alSource);
                    }
                    else
                    {
                        int num;
                        AL.GetSource(sndInst.alSource, ALGetSourcei.BuffersProcessed, out num);
                        while (num > 0)
                        {
                            num--;

                            int unqueued;
                            unqueued = AL.SourceUnqueueBuffer(sndInst.alSource);

                            if (sndInst.strOvStr != IntPtr.Zero)
                            {
                                PcmData pcm;
                                bool    eof = !OV.StreamChunk(sndInst.strOvStr, out pcm);
                                if (pcm.data.Length > 0)
                                {
                                    AL.BufferData(
                                        unqueued,
                                        pcm.channelCount == 1 ? ALFormat.Mono16 : ALFormat.Stereo16,
                                        pcm.data,
                                        pcm.data.Length,
                                        pcm.sampleRate);
                                }
                                AL.SourceQueueBuffer(sndInst.alSource, unqueued);
                                if (eof && pcm.data.Length == 0)
                                {
                                    OV.EndStream(ref sndInst.strOvStr);
                                    if (sndInst.looped)
                                    {
                                        OV.BeginStreamFromMemory(res.Data.Res.OggVorbisData, out sndInst.strOvStr);
                                    }
                                    else
                                    {
                                        sndInst.strStopReq = true;
                                        break;
                                    }
                                }
                            }
                        }
                    }

                    if (stateTemp == ALSourceState.Stopped && !sndInst.strStopReq)
                    {
                        // If the source stopped unintentionally, restart it. (See above)
                        AL.SourcePlay(sndInst.alSource);
                    }
                }
                Thread.Sleep(8);
            }
        }
예제 #27
0
 public void Pause()
 {
     AL.SourcePause(Source);
     SourceState = AL.GetSourceState(Source);
 }
예제 #28
0
        public bool IsStopped()
        {
            ALSourceState state = AL.GetSourceState(mySource);

            return(state == ALSourceState.Stopped);
        }
예제 #29
0
		public bool Play () {
			if (_music == null)
				return false;

			if (!EnqueueBuffers())
				return false;

			_userState = ALSourceState.Playing;
			while (AL.GetSourceState(_source) != ALSourceState.Playing)
				Thread.Sleep(1);
			return true;
		}
예제 #30
0
 public void Stop()
 {
     AL.SourceStop(Source);
     SourceState = AL.GetSourceState(Source);
 }
예제 #31
0
 private static ChannelState ALSourceStateToChannelState(ALSourceState alSourceState)
 {
     switch (alSourceState)
     {
         case ALSourceState.Playing:
             return ChannelState.Playing;
         case ALSourceState.Paused:
             return ChannelState.Paused;
         default:
             return ChannelState.Stopped;
     }
 }
예제 #32
0
        /// <summary>
        /// Updates the SoundInstance
        /// </summary>
        public void Update()
        {
            if (!DualityApp.Sound.IsAvailable)
            {
                return;
            }

            lock (this.strLock)
            {
                // Check existence of attachTo object
                if (this.attachedTo != null && this.attachedTo.Disposed)
                {
                    this.attachedTo = null;
                }

                // Retrieve sound resource values
                Sound     soundRes     = this.sound.Res;
                AudioData audioDataRes = this.audioData.Res;
                if (soundRes == null || audioDataRes == null)
                {
                    this.Dispose();
                    return;
                }
                float optVolFactor = this.GetTypeVolFactor();
                float minDistTemp  = soundRes.MinDist;
                float maxDistTemp  = soundRes.MaxDist;
                float volTemp      = optVolFactor * soundRes.VolumeFactor * this.vol * this.curFade * this.pauseFade;
                float pitchTemp    = soundRes.PitchFactor * this.pitch;
                float priorityTemp = 1000.0f;
                priorityTemp *= volTemp;

                // Calculate 3D source values, distance and priority
                Vector3 posAbs = this.pos;
                Vector3 velAbs = this.vel;
                if (this.is3D)
                {
                    Components.Transform attachTransform = this.attachedTo != null ? this.attachedTo.Transform : null;

                    // Attach to object
                    if (this.attachedTo != null && this.attachedTo != DualityApp.Sound.Listener)
                    {
                        MathF.TransformCoord(ref posAbs.X, ref posAbs.Y, attachTransform.Angle);
                        MathF.TransformCoord(ref velAbs.X, ref velAbs.Y, attachTransform.Angle);
                        posAbs += attachTransform.Pos;
                        velAbs += attachTransform.Vel;
                    }

                    // Distance check
                    Vector3 listenerPos = DualityApp.Sound.ListenerPos;
                    float   dist;
                    if (this.attachedTo != DualityApp.Sound.Listener)
                    {
                        dist = MathF.Sqrt(
                            (posAbs.X - listenerPos.X) * (posAbs.X - listenerPos.X) +
                            (posAbs.Y - listenerPos.Y) * (posAbs.Y - listenerPos.Y) +
                            (posAbs.Z - listenerPos.Z) * (posAbs.Z - listenerPos.Z) * 0.25f);
                    }
                    else
                    {
                        dist = MathF.Sqrt(
                            posAbs.X * posAbs.X +
                            posAbs.Y * posAbs.Y +
                            posAbs.Z * posAbs.Z * 0.25f);
                    }
                    if (dist > maxDistTemp)
                    {
                        this.Dispose();
                        return;
                    }
                    else
                    {
                        priorityTemp *= Math.Max(0.0f, 1.0f - (dist - minDistTemp) / (maxDistTemp - minDistTemp));
                    }
                }

                // Grab an OpenAL source, if not yet assigned
                if (this.alSource == AlSource_NotYetAssigned)
                {
                    if (this.GrabAlSource())
                    {
                        this.RegisterPlaying();
                    }
                    else
                    {
                        this.Dispose();
                        return;
                    }
                }

                // Determine source state, if available
                ALSourceState stateTemp       = ALSourceState.Stopped;
                bool          sourceAvailable = this.alSource > AlSource_NotAvailable;
                if (sourceAvailable)
                {
                    stateTemp = AL.GetSourceState(this.alSource);
                }

                // If the source is stopped / finished, dispose and return
                if (stateTemp == ALSourceState.Stopped && (!audioDataRes.IsStreamed || this.strStopReq != StopRequest.None))
                {
                    this.Dispose();
                    return;
                }
                else if (stateTemp == ALSourceState.Initial && this.strStopReq == StopRequest.Immediately)
                {
                    this.Dispose();
                    return;
                }

                // Fading in and out
                bool fadeOut = this.fadeTarget <= 0.0f;
                if (!this.paused)
                {
                    if (this.fadeTarget != this.curFade)
                    {
                        float fadeTemp = Time.TimeMult * Time.SPFMult / Math.Max(0.05f, this.fadeTimeSec);

                        if (this.fadeTarget > this.curFade)
                        {
                            this.curFade += fadeTemp;
                        }
                        else
                        {
                            this.curFade -= fadeTemp;
                        }

                        if (Math.Abs(this.curFade - this.fadeTarget) < fadeTemp * 2.0f)
                        {
                            this.curFade = this.fadeTarget;
                        }

                        this.dirtyState |= DirtyFlag.Vol;
                    }
                }

                // Special paused-fading
                if (this.paused && this.pauseFade > 0.0f)
                {
                    this.pauseFade   = MathF.Max(0.0f, this.pauseFade - Time.TimeMult * Time.SPFMult * 5.0f);
                    this.dirtyState |= DirtyFlag.Paused | DirtyFlag.Vol;
                }
                else if (!this.paused && this.pauseFade < 1.0f)
                {
                    this.pauseFade   = MathF.Min(1.0f, this.pauseFade + Time.TimeMult * Time.SPFMult * 5.0f);
                    this.dirtyState |= DirtyFlag.Paused | DirtyFlag.Vol;
                }

                // SlowMotion
                //if (this.type == SoundType.EffectWorld)
                //{
                //    pitchTemp *= (float)Math.Max(0.5d, SteApp.Current.SlowMotion);
                //    volTemp *= 2.0f * (float)Math.Min(0.5d, SteApp.Current.SlowMotion);

                //    // Hack: Pitch always dirty
                //    this.dirtyState |= DirtyFlag.Pitch;
                //}
                //else if (this.type == SoundType.Speech)
                //{
                //    volTemp *= (float)Math.Sqrt(SteApp.Current.SlowMotion);
                //}

                // Hack: Volume always dirty - just to be sure
                this.dirtyState |= DirtyFlag.Vol;

                if (sourceAvailable)
                {
                    if (this.is3D)
                    {
                        // Hack: Relative always dirty to support switching listeners without establishing a notifier-event
                        this.dirtyState |= DirtyFlag.Relative;
                        if (this.attachedTo != null)
                        {
                            this.dirtyState |= DirtyFlag.AttachedTo;
                        }

                        if ((this.dirtyState & DirtyFlag.Relative) != DirtyFlag.None)
                        {
                            AL.Source(this.alSource, ALSourceb.SourceRelative, this.attachedTo == DualityApp.Sound.Listener);
                        }
                        if ((this.dirtyState & DirtyFlag.Pos) != DirtyFlag.None)
                        {
                            AL.Source(this.alSource, ALSource3f.Position, posAbs.X, -posAbs.Y, -posAbs.Z * 0.5f);
                        }
                        if ((this.dirtyState & DirtyFlag.Vel) != DirtyFlag.None)
                        {
                            AL.Source(this.alSource, ALSource3f.Velocity, velAbs.X, -velAbs.Y, -velAbs.Z);
                        }
                    }
                    else
                    {
                        if ((this.dirtyState & DirtyFlag.Relative) != DirtyFlag.None)
                        {
                            AL.Source(this.alSource, ALSourceb.SourceRelative, true);
                        }
                        if ((this.dirtyState & DirtyFlag.Pos) != DirtyFlag.None)
                        {
                            AL.Source(this.alSource, ALSource3f.Position, 0.0f, 0.0f, 0.0f);
                        }
                        if ((this.dirtyState & DirtyFlag.Vel) != DirtyFlag.None)
                        {
                            AL.Source(this.alSource, ALSource3f.Velocity, 0.0f, 0.0f, 0.0f);
                        }
                    }
                    if ((this.dirtyState & DirtyFlag.MaxDist) != DirtyFlag.None)
                    {
                        AL.Source(this.alSource, ALSourcef.MaxDistance, maxDistTemp);
                    }
                    if ((this.dirtyState & DirtyFlag.RefDist) != DirtyFlag.None)
                    {
                        AL.Source(this.alSource, ALSourcef.ReferenceDistance, minDistTemp);
                    }
                    if ((this.dirtyState & DirtyFlag.Loop) != DirtyFlag.None)
                    {
                        AL.Source(this.alSource, ALSourceb.Looping, (this.looped && !audioDataRes.IsStreamed));
                    }
                    if ((this.dirtyState & DirtyFlag.Vol) != DirtyFlag.None)
                    {
                        AL.Source(this.alSource, ALSourcef.Gain, volTemp);
                    }
                    if ((this.dirtyState & DirtyFlag.Pitch) != DirtyFlag.None)
                    {
                        AL.Source(this.alSource, ALSourcef.Pitch, pitchTemp);
                    }
                    if ((this.dirtyState & DirtyFlag.Paused) != DirtyFlag.None)
                    {
                        if (this.paused && this.pauseFade == 0.0f && stateTemp == ALSourceState.Playing)
                        {
                            AL.SourcePause(this.alSource);
                        }
                        else if ((!this.paused || this.pauseFade > 0.0f) && stateTemp == ALSourceState.Paused)
                        {
                            AL.SourcePlay(this.alSource);
                        }
                    }
                }
                this.dirtyState = DirtyFlag.None;

                // Update play time
                if (!this.paused)
                {
                    this.playTime += MathF.Max(0.5f, pitchTemp) * Time.TimeMult * Time.SPFMult;
                    if (this.sound.Res.FadeOutAt > 0.0f && this.playTime >= this.sound.Res.FadeOutAt)
                    {
                        this.FadeOut(this.sound.Res.FadeOutTime);
                    }
                }

                // Finish priority calculation
                this.curPriority = (int)Math.Round(priorityTemp / Math.Sqrt(DualityApp.Sound.GetNumPlaying(this.sound)));

                // Initially play the source
                if (stateTemp == ALSourceState.Initial && !this.paused)
                {
                    if (audioDataRes.IsStreamed)
                    {
                        this.isStreamed = true;
                        DualityApp.Sound.EnqueueForStreaming(this);
                    }
                    else
                    {
                        AL.SourceQueueBuffer(this.alSource, audioDataRes.AlBuffer);
                        AL.SourcePlay(this.alSource);
                    }
                }

                // Remove faded out sources
                if (fadeOut && volTemp <= 0.0f)
                {
                    this.fadeWaitEnd += Time.TimeMult * Time.MsPFMult;
                    // After fading out entirely, wait 50 ms before actually stopping the source to prevent unpleasant audio tick / glitch noises
                    if (this.fadeWaitEnd > 50.0f)
                    {
                        this.Dispose();
                        return;
                    }
                }
                else
                {
                    this.fadeWaitEnd = 0.0f;
                }
            }
        }
예제 #33
0
        public bool IsPlaying()
        {
            ALSourceState state = AL.GetSourceState(mySource);

            return(state == ALSourceState.Playing);
        }