public void Clear()
 {
     state = AudioSourceState.FREE;
     audioSource.Stop();
     transform.localPosition = new Vector3(0, 0, 0);
     targetTransform         = null;
 }
Example #2
0
    public IEnumerator Reset()
    {
        Debug.Log("Reset");

        yield return(new WaitForSeconds(1));

        state = AudioSourceState.Stop;

        PreLoad();
    }
Example #3
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;
            }
        }
Example #4
0
        void INativeAudioSource.ApplyState(ref AudioSourceState state)
        {
            // ToDo: Implement velocity
            // ToDo: Implement pitch
            // ToDo: Implement lowpass
            // ToDo: Implement pause

            if (isFirstUpdate ||
                LastState.RelativeToListener != state.RelativeToListener ||
                LastState.Position != state.Position ||
                LastState.MaxDistance != state.MaxDistance ||
                LastState.MinDistance != state.MinDistance ||
                LastState.Volume != state.Volume)
            {
                Vector3 distance;
                if (state.RelativeToListener)
                {
                    distance = state.Position;
                }
                else
                {
                    distance = state.Position - AudioBackend.ActiveInstance.ListenerPosition;
                }

                float maxDistance   = (state.MaxDistance - state.MinDistance);
                float distanceRatio = (Math.Max(distance.Length - state.MinDistance, 0) / maxDistance);
                distanceRatio = state.Volume * (1f - distanceRatio * distanceRatio);

                float distanceSideRatio = MathF.Sign(distance.X) * Math.Max(Math.Abs(distance.X) - state.MinDistance * 0.5f, 0) / maxDistance;
                if (Math.Abs(distanceSideRatio) < 0.00001f)
                {
                    VolumeLeft = VolumeRight = 1f;
                }
                else
                {
                    const float stereoSeparation = 0.5f;

                    float ratio = MathF.Clamp(distanceSideRatio * 8f, -stereoSeparation, stereoSeparation);
                    VolumeLeft  = stereoSeparation - ratio;
                    VolumeRight = stereoSeparation + ratio;
                }

                VolumeLeft  *= distanceRatio;
                VolumeRight *= distanceRatio;
            }

            LastState        = state;
            LastState.Looped = state.Looped && !IsStreamed;
            isFirstUpdate    = false;
        }
Example #5
0
        /// <summary>
        /// Updates the SoundInstance
        /// </summary>
        public void Update()
        {
            // 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;
            }

            // Set up local variables for state calculation
            Vector3          listenerPos        = DualityApp.Sound.ListenerPos;
            bool             attachedToListener = this.attachedTo != null && ((this.attachedTo == DualityApp.Sound.Listener) || this.attachedTo.IsChildOf(DualityApp.Sound.Listener));
            float            optVolFactor       = this.GetTypeVolFactor();
            float            priorityTemp       = 1000.0f;
            AudioSourceState nativeState        = AudioSourceState.Default;

            nativeState.MinDistance = soundRes.MinDist;
            nativeState.MaxDistance = soundRes.MaxDist;
            nativeState.Volume      = optVolFactor * soundRes.VolumeFactor * this.vol * this.curFade * this.pauseFade;
            nativeState.Pitch       = soundRes.PitchFactor * this.pitch;
            nativeState.Lowpass     = soundRes.LowpassFactor * this.lowpass;
            priorityTemp           *= nativeState.Volume;

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

                // Attach to object
                if (this.attachedTo != null)
                {
                    MathF.TransformCoord(ref nativeState.Position.X, ref nativeState.Position.Y, attachTransform.Angle);
                    MathF.TransformCoord(ref nativeState.Velocity.X, ref nativeState.Velocity.Y, attachTransform.Angle);
                    nativeState.Position += attachTransform.Pos;
                    nativeState.Velocity += attachTransform.Vel;
                }

                // Distance check
                float dist = MathF.Sqrt(
                    (nativeState.Position.X - listenerPos.X) * (nativeState.Position.X - listenerPos.X) +
                    (nativeState.Position.Y - listenerPos.Y) * (nativeState.Position.Y - listenerPos.Y) +
                    (nativeState.Position.Z - listenerPos.Z) * (nativeState.Position.Z - listenerPos.Z) * 0.25f);
                if (dist > nativeState.MaxDistance)
                {
                    this.Dispose();
                    return;
                }
                else
                {
                    priorityTemp *= Math.Max(0.0f, 1.0f - (dist - nativeState.MinDistance) / (nativeState.MaxDistance - nativeState.MinDistance));
                }
            }

            if (this.notYetAssigned)
            {
                // Grab a native audio source
                if (this.GrabNativeSource())
                {
                    this.RegisterPlaying();
                }
                // If there is none available, just stop right there.
                else
                {
                    this.Dispose();
                    return;
                }
            }

            // If the source is stopped / finished, dispose and return
            if (this.native == null || this.native.IsFinished)
            {
                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;
                    }
                }
            }

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

            // Apply the sounds state to its internal native audio source
            if (this.native != null)
            {
                if (this.is3D)
                {
                    nativeState.RelativeToListener = attachedToListener;
                    if (attachedToListener)
                    {
                        nativeState.Position -= listenerPos;
                    }

                    // Convert from Duality units to (physical) audio backend units.
                    nativeState.Position    *= AudioUnit.LengthToPhysical;
                    nativeState.Velocity    *= AudioUnit.VelocityToPhysical;
                    nativeState.MinDistance *= AudioUnit.LengthToPhysical;
                    nativeState.MaxDistance *= AudioUnit.LengthToPhysical;

                    // Post-process sound instance data in listener space
                    float   listenerAngle = DualityApp.Sound.ListenerAngle;
                    Vector3 adjustedPos   = nativeState.RelativeToListener ? nativeState.Position : nativeState.Position - listenerPos * AudioUnit.LengthToPhysical;
                    MathF.TransformCoord(ref adjustedPos.X, ref adjustedPos.Z, -listenerAngle);

                    // Flatten depth position a little, so far away sounds that can still be seen appear louder
                    adjustedPos.Z *= 0.5f;

                    // Normalize audio position for smooth panning when near. Do it in physical
                    // units, so this remains constant regardless of unit changes.
                    float smoothPanRadius   = 5.0f;
                    float listenerSpaceDist = adjustedPos.Length;
                    if (listenerSpaceDist < smoothPanRadius)
                    {
                        float panningActive = listenerSpaceDist / smoothPanRadius;

                        adjustedPos = Vector3.Lerp(
                            new Vector3(0.0f, 0.0f, 1.0f + (smoothPanRadius - 1.0f) * panningActive),
                            adjustedPos,
                            panningActive);
                    }

                    MathF.TransformCoord(ref adjustedPos.X, ref adjustedPos.Z, listenerAngle);
                    nativeState.Position = nativeState.RelativeToListener ? adjustedPos : adjustedPos + listenerPos * AudioUnit.LengthToPhysical;
                }
                else
                {
                    // We'll do a +/- 30° panning for 2D audio
                    Vector2 localPos = Vector2.FromAngleLength(
                        MathF.DegToRad(30.0f * this.panning),
                        1.0f);

                    nativeState.RelativeToListener = true;
                    nativeState.Position           = new Vector3(localPos.X, 0.0f, -localPos.Y);
                    nativeState.Velocity           = Vector3.Zero;
                }
                nativeState.Looped = this.looped;
                nativeState.Paused = this.paused && this.pauseFade == 0.0f;

                this.native.ApplyState(ref nativeState);
            }

            // Update play time
            if (!this.paused)
            {
                this.playTime += MathF.Max(0.5f, nativeState.Pitch) * 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 (this.native.IsInitial && !this.paused)
            {
                if (audioDataRes.IsStreamed)
                {
                    this.native.Play(this);
                }
                else if (audioDataRes.Native != null)
                {
                    this.native.Play(audioDataRes.Native);
                }
            }

            // Remove faded out sources
            if (fadeOut && nativeState.Volume <= 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;
            }
        }
Example #6
0
        public void Update()
        {
            AudioSourceState nativeState = AudioSourceState.Default;

            nativeState.Volume  = SettingsCache.MusicVolume * curFade;
            nativeState.Lowpass = this.lowpass;

            bool fadeOut = this.fadeTarget <= 0.0f;

            if (this.fadeTarget != this.curFade)
            {
                float fadeTemp = Time.TimeMult * Time.SecondsPerFrame / 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;
                }
            }

            if (this.notYetAssigned)
            {
                this.notYetAssigned = false;

                // Grab a native audio source
                if (openmpt_module == IntPtr.Zero)
                {
                    this.Dispose();
                    return;
                }

                native = DualityApp.AudioBackend.CreateSource();
                native.Play(this);
            }

            // If the source is stopped / finished, dispose and return
            if (this.native == null || this.native.IsFinished)
            {
                this.Dispose();
                return;
            }

            if (fadeOut && nativeState.Volume <= 0.0f)
            {
                this.fadeWaitEnd += Time.TimeMult * Time.MillisecondsPerFrame;
                // 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;
            }

            native.ApplyState(ref nativeState);
        }
Example #7
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;
            }
        }
Example #8
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;
			}
		}
Example #9
0
 void INativeAudioSource.ApplyState(ref AudioSourceState state)
 {
     this.finished = true;
 }
		void INativeAudioSource.ApplyState(ref AudioSourceState state)
		{
			this.finished = true;
		}
Example #11
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;
            }
        }
Example #12
0
        /// <summary>
        /// Updates the SoundInstance
        /// </summary>
        public void Update()
        {
            // 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;
            }

            // Set up local variables for state calculation
            Vector3          listenerPos        = DualityApp.Sound.ListenerPos;
            bool             attachedToListener = this.attachedTo != null && ((this.attachedTo == DualityApp.Sound.Listener) || this.attachedTo.IsChildOf(DualityApp.Sound.Listener));
            float            optVolFactor       = this.GetTypeVolFactor();
            float            priorityTemp       = 1000.0f;
            AudioSourceState nativeState        = AudioSourceState.Default;

            nativeState.MinDistance = soundRes.MinDist;
            nativeState.MaxDistance = soundRes.MaxDist;
            nativeState.Volume      = optVolFactor * soundRes.VolumeFactor * this.vol * this.curFade * this.pauseFade;
            nativeState.Pitch       = soundRes.PitchFactor * this.pitch;
            nativeState.Lowpass     = soundRes.LowpassFactor * this.lowpass;
            priorityTemp           *= nativeState.Volume;

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

                // Attach to object
                if (this.attachedTo != null)
                {
                    MathF.TransformCoord(ref nativeState.Position.X, ref nativeState.Position.Y, attachTransform.Angle);
                    MathF.TransformCoord(ref nativeState.Velocity.X, ref nativeState.Velocity.Y, attachTransform.Angle);
                    nativeState.Position += attachTransform.Pos;
                    nativeState.Velocity += attachTransform.Vel;
                }

                // Distance check
                float dist = MathF.Sqrt(
                    (nativeState.Position.X - listenerPos.X) * (nativeState.Position.X - listenerPos.X) +
                    (nativeState.Position.Y - listenerPos.Y) * (nativeState.Position.Y - listenerPos.Y) +
                    (nativeState.Position.Z - listenerPos.Z) * (nativeState.Position.Z - listenerPos.Z) * 0.25f);
                if (dist > nativeState.MaxDistance)
                {
                    this.Dispose();
                    return;
                }
                else
                {
                    priorityTemp *= Math.Max(0.0f, 1.0f - (dist - nativeState.MinDistance) / (nativeState.MaxDistance - nativeState.MinDistance));
                }
            }

            if (this.notYetAssigned)
            {
                // Grab a native audio source
                if (this.GrabNativeSource())
                {
                    this.RegisterPlaying();
                }
                // If there is none available, just stop right there.
                else
                {
                    this.Dispose();
                    return;
                }
            }

            // If the source is stopped / finished, dispose and return
            if (this.native == null || this.native.IsFinished)
            {
                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;
                    }
                }
            }

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

            // Apply the sounds state to its internal native audio source
            if (this.native != null)
            {
                if (this.is3D)
                {
                    nativeState.RelativeToListener = attachedToListener;
                    if (attachedToListener)
                    {
                        nativeState.Position -= listenerPos;
                    }
                }
                else
                {
                    nativeState.RelativeToListener = true;
                    nativeState.Position           = new Vector3(this.panning, 0.0f, 0.0f);
                    nativeState.Velocity           = Vector3.Zero;
                }
                nativeState.Looped = this.looped;
                nativeState.Paused = this.paused && this.pauseFade == 0.0f;

                this.native.ApplyState(ref nativeState);
            }

            // Update play time
            if (!this.paused)
            {
                this.playTime += MathF.Max(0.5f, nativeState.Pitch) * 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 (this.native.IsInitial && !this.paused)
            {
                if (audioDataRes.IsStreamed)
                {
                    this.native.Play(this);
                }
                else if (audioDataRes.Native != null)
                {
                    this.native.Play(audioDataRes.Native);
                }
            }

            // Remove faded out sources
            if (fadeOut && nativeState.Volume <= 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;
            }
        }