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 HashSet<WeakReference> resources = new HashSet<WeakReference>();
 | 
				
			||||||
		private readonly List<StreamingSound> autoUpdateStreamingSoundReferences = new List<StreamingSound>();
 | 
							private readonly List<StreamingSound> autoUpdateStreamingSoundReferences = new List<StreamingSound>();
 | 
				
			||||||
		private readonly List<StaticSoundInstance> autoFreeStaticSoundInstanceReferences = new List<StaticSoundInstance>();
 | 
							private readonly List<StaticSoundInstance> autoFreeStaticSoundInstanceReferences = new List<StaticSoundInstance>();
 | 
				
			||||||
 | 
							private readonly List<WeakReference<SoundQueue>> soundQueueReferences = new List<WeakReference<SoundQueue>>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		private AudioTweenManager AudioTweenManager;
 | 
							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);
 | 
								AudioTweenManager.Update(elapsedSeconds);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -256,6 +269,11 @@ namespace MoonWorks.Audio
 | 
				
			||||||
			autoFreeStaticSoundInstanceReferences.Add(instance);
 | 
								autoFreeStaticSoundInstanceReferences.Add(instance);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							internal void AddSoundQueueReference(SoundQueue queue)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								soundQueueReferences.Add(new WeakReference<SoundQueue>(queue));
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		protected virtual void Dispose(bool disposing)
 | 
							protected virtual void Dispose(bool disposing)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			if (!IsDisposed)
 | 
								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