forked from MoonsideGames/MoonWorks
				
			add SoundQueue
							parent
							
								
									dbbd6540ab
								
							
						
					
					
						commit
						1d86d0c210
					
				| 
						 | 
				
			
			@ -30,6 +30,7 @@ namespace MoonWorks.Audio
 | 
			
		|||
		private readonly HashSet<WeakReference> resources = new HashSet<WeakReference>();
 | 
			
		||||
		private readonly List<StreamingSound> autoUpdateStreamingSoundReferences = new List<StreamingSound>();
 | 
			
		||||
		private readonly List<StaticSoundInstance> autoFreeStaticSoundInstanceReferences = new List<StaticSoundInstance>();
 | 
			
		||||
		private readonly List<WeakReference<SoundQueue>> soundQueueReferences = new List<WeakReference<SoundQueue>>();
 | 
			
		||||
 | 
			
		||||
		private AudioTweenManager AudioTweenManager;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -184,6 +185,18 @@ namespace MoonWorks.Audio
 | 
			
		|||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			for (var i = soundQueueReferences.Count - 1; i >= 0; i -= 1)
 | 
			
		||||
			{
 | 
			
		||||
				if (soundQueueReferences[i].TryGetTarget(out var soundQueue))
 | 
			
		||||
				{
 | 
			
		||||
					soundQueue.Update();
 | 
			
		||||
				}
 | 
			
		||||
				else
 | 
			
		||||
				{
 | 
			
		||||
					soundQueueReferences.RemoveAt(i);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			AudioTweenManager.Update(elapsedSeconds);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -256,6 +269,11 @@ namespace MoonWorks.Audio
 | 
			
		|||
			autoFreeStaticSoundInstanceReferences.Add(instance);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		internal void AddSoundQueueReference(SoundQueue queue)
 | 
			
		||||
		{
 | 
			
		||||
			soundQueueReferences.Add(new WeakReference<SoundQueue>(queue));
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		protected virtual void Dispose(bool disposing)
 | 
			
		||||
		{
 | 
			
		||||
			if (!IsDisposed)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,132 @@
 | 
			
		|||
using System;
 | 
			
		||||
 | 
			
		||||
namespace MoonWorks.Audio
 | 
			
		||||
{
 | 
			
		||||
	// NOTE: all sounds played with a playlist must have the same audio format!
 | 
			
		||||
	public class SoundQueue : SoundInstance
 | 
			
		||||
	{
 | 
			
		||||
		public int NeedBufferThreshold = 0;
 | 
			
		||||
		private uint queuedBufferCount = 0;
 | 
			
		||||
 | 
			
		||||
		public delegate void OnBufferNeededFunc();
 | 
			
		||||
		public OnBufferNeededFunc OnBufferNeeded;
 | 
			
		||||
 | 
			
		||||
		private object StateLock = new object();
 | 
			
		||||
 | 
			
		||||
		public SoundQueue(AudioDevice device, ushort formatTag, ushort bitsPerSample, ushort blockAlign, ushort channels, uint samplesPerSecond) : base(device, formatTag, bitsPerSample, blockAlign, channels, samplesPerSecond)
 | 
			
		||||
		{
 | 
			
		||||
			device.AddSoundQueueReference(this);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public SoundQueue(AudioDevice device, StaticSound templateSound) : base(device, templateSound.FormatTag, templateSound.BitsPerSample, templateSound.BlockAlign, templateSound.Channels, templateSound.SamplesPerSecond)
 | 
			
		||||
		{
 | 
			
		||||
			device.AddSoundQueueReference(this);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public void Update()
 | 
			
		||||
		{
 | 
			
		||||
			lock (StateLock)
 | 
			
		||||
			{
 | 
			
		||||
				if (IsDisposed) { return; }
 | 
			
		||||
				if (State != SoundState.Playing) { return; }
 | 
			
		||||
 | 
			
		||||
				if (NeedBufferThreshold > 0)
 | 
			
		||||
				{
 | 
			
		||||
					FAudio.FAudioSourceVoice_GetState(
 | 
			
		||||
						Voice,
 | 
			
		||||
						out var state,
 | 
			
		||||
						FAudio.FAUDIO_VOICE_NOSAMPLESPLAYED
 | 
			
		||||
					);
 | 
			
		||||
 | 
			
		||||
					var queuedBufferCount = state.BuffersQueued;
 | 
			
		||||
					for (int i = 0; i < NeedBufferThreshold - queuedBufferCount; i += 1)
 | 
			
		||||
					{
 | 
			
		||||
						if (OnBufferNeeded != null)
 | 
			
		||||
						{
 | 
			
		||||
							OnBufferNeeded();
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public void EnqueueSound(StaticSound sound)
 | 
			
		||||
		{
 | 
			
		||||
#if DEBUG
 | 
			
		||||
			if (
 | 
			
		||||
				sound.FormatTag != Format.wFormatTag ||
 | 
			
		||||
				sound.BitsPerSample != Format.wBitsPerSample ||
 | 
			
		||||
				sound.Channels != Format.nChannels ||
 | 
			
		||||
				sound.SamplesPerSecond != Format.nSamplesPerSec
 | 
			
		||||
			)
 | 
			
		||||
			{
 | 
			
		||||
				Logger.LogWarn("Playlist audio format mismatch!");
 | 
			
		||||
			}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
			lock (StateLock)
 | 
			
		||||
			{
 | 
			
		||||
				FAudio.FAudioSourceVoice_SubmitSourceBuffer(
 | 
			
		||||
					Voice,
 | 
			
		||||
					ref sound.Handle,
 | 
			
		||||
					IntPtr.Zero
 | 
			
		||||
				);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public override void Pause()
 | 
			
		||||
		{
 | 
			
		||||
			lock (StateLock)
 | 
			
		||||
			{
 | 
			
		||||
				if (State == SoundState.Playing)
 | 
			
		||||
				{
 | 
			
		||||
					FAudio.FAudioSourceVoice_Stop(Voice, 0, 0);
 | 
			
		||||
					State = SoundState.Paused;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public override void Play()
 | 
			
		||||
		{
 | 
			
		||||
			PlayUsingOperationSet(0);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public override void QueueSyncPlay()
 | 
			
		||||
		{
 | 
			
		||||
			PlayUsingOperationSet(1);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private void PlayUsingOperationSet(uint operationSet)
 | 
			
		||||
		{
 | 
			
		||||
			lock (StateLock)
 | 
			
		||||
			{
 | 
			
		||||
				if (State == SoundState.Playing)
 | 
			
		||||
				{
 | 
			
		||||
					return;
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				FAudio.FAudioSourceVoice_Start(Voice, 0, operationSet);
 | 
			
		||||
				State = SoundState.Playing;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public override void Stop()
 | 
			
		||||
		{
 | 
			
		||||
			lock (StateLock)
 | 
			
		||||
			{
 | 
			
		||||
				FAudio.FAudioSourceVoice_ExitLoop(Voice, 0);
 | 
			
		||||
				State = SoundState.Stopped;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public override void StopImmediate()
 | 
			
		||||
		{
 | 
			
		||||
			lock (StateLock)
 | 
			
		||||
			{
 | 
			
		||||
				FAudio.FAudioSourceVoice_Stop(Voice, 0, 0);
 | 
			
		||||
				FAudio.FAudioSourceVoice_FlushSourceBuffers(Voice);
 | 
			
		||||
				State = SoundState.Stopped;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue