optimize StreamingSound allocation and update
							parent
							
								
									b4a0c7de88
								
							
						
					
					
						commit
						dc7e68fecc
					
				|  | @ -1,23 +1,22 @@ | |||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Runtime.InteropServices; | ||||
| 
 | ||||
| namespace MoonWorks.Audio | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// For streaming long playback. | ||||
| 	/// Can be extended to support custom decoders. | ||||
| 	/// Must be extended with a decoder routine called by FillBuffer. | ||||
| 	/// See StreamingSoundOgg for an example. | ||||
| 	/// </summary> | ||||
| 	public abstract class StreamingSound : SoundInstance | ||||
| 	{ | ||||
| 		private readonly List<IntPtr> queuedBuffers = new List<IntPtr>(); | ||||
| 		private const int MINIMUM_BUFFER_CHECK = 3; | ||||
| 
 | ||||
| 		private int PendingBufferCount => queuedBuffers.Count; | ||||
| 
 | ||||
| 		private const int BUFFER_COUNT = 3; | ||||
| 		private readonly IntPtr[] buffers; | ||||
| 		private int nextBufferIndex = 0; | ||||
| 		private uint queuedBufferCount = 0; | ||||
| 		public abstract int BUFFER_SIZE { get; } | ||||
| 
 | ||||
| 		public StreamingSound( | ||||
| 		public unsafe StreamingSound( | ||||
| 			AudioDevice device, | ||||
| 			ushort formatTag, | ||||
| 			ushort bitsPerSample, | ||||
|  | @ -27,6 +26,12 @@ namespace MoonWorks.Audio | |||
| 		) : base(device, formatTag, bitsPerSample, blockAlign, channels, samplesPerSecond) | ||||
| 		{ | ||||
| 			device.AddDynamicSoundInstance(this); | ||||
| 
 | ||||
| 			buffers = new IntPtr[BUFFER_COUNT]; | ||||
| 			for (int i = 0; i < BUFFER_COUNT; i += 1) | ||||
| 			{ | ||||
| 				buffers[i] = (IntPtr) NativeMemory.Alloc((nuint) BUFFER_SIZE); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		public override void Play() | ||||
|  | @ -78,25 +83,14 @@ namespace MoonWorks.Audio | |||
| 				FAudio.FAUDIO_VOICE_NOSAMPLESPLAYED | ||||
| 			); | ||||
| 
 | ||||
| 			while (PendingBufferCount > state.BuffersQueued) | ||||
| 			{ | ||||
| 				lock (queuedBuffers) | ||||
| 				{ | ||||
| 					NativeMemory.Free((void*) queuedBuffers[0]); | ||||
| 					queuedBuffers.RemoveAt(0); | ||||
| 				} | ||||
| 			} | ||||
| 			queuedBufferCount = state.BuffersQueued; | ||||
| 
 | ||||
| 			QueueBuffers(); | ||||
| 		} | ||||
| 
 | ||||
| 		protected void QueueBuffers() | ||||
| 		{ | ||||
| 			for ( | ||||
| 				int i = MINIMUM_BUFFER_CHECK - PendingBufferCount; | ||||
| 				i > 0; | ||||
| 				i -= 1 | ||||
| 			) | ||||
| 			for (int i = 0; i < BUFFER_COUNT - queuedBufferCount; i += 1) | ||||
| 			{ | ||||
| 				AddBuffer(); | ||||
| 			} | ||||
|  | @ -104,51 +98,40 @@ namespace MoonWorks.Audio | |||
| 
 | ||||
| 		protected unsafe void ClearBuffers() | ||||
| 		{ | ||||
| 			lock (queuedBuffers) | ||||
| 			{ | ||||
| 				foreach (IntPtr buf in queuedBuffers) | ||||
| 				{ | ||||
| 					NativeMemory.Free((void*) buf); | ||||
| 				} | ||||
| 				queuedBuffers.Clear(); | ||||
| 			} | ||||
| 			nextBufferIndex = 0; | ||||
| 			queuedBufferCount = 0; | ||||
| 		} | ||||
| 
 | ||||
| 		protected unsafe void AddBuffer() | ||||
| 		{ | ||||
| 			void* buffer = NativeMemory.Alloc((nuint) BUFFER_SIZE); | ||||
| 			var buffer = buffers[nextBufferIndex]; | ||||
| 			nextBufferIndex = (nextBufferIndex + 1) % BUFFER_COUNT; | ||||
| 
 | ||||
| 			FillBuffer( | ||||
| 				buffer, | ||||
| 				(void*) buffer, | ||||
| 				BUFFER_SIZE, | ||||
| 				out int filledLengthInBytes, | ||||
| 				out bool reachedEnd | ||||
| 			); | ||||
| 
 | ||||
| 			lock (queuedBuffers) | ||||
| 			FAudio.FAudioBuffer buf = new FAudio.FAudioBuffer | ||||
| 			{ | ||||
| 				queuedBuffers.Add((IntPtr) buffer); | ||||
| 				if (State != SoundState.Stopped) | ||||
| 				{ | ||||
| 					FAudio.FAudioBuffer buf = new FAudio.FAudioBuffer | ||||
| 					{ | ||||
| 						AudioBytes = (uint) filledLengthInBytes, | ||||
| 						pAudioData = (IntPtr) buffer, | ||||
| 						PlayLength = ( | ||||
| 							(uint) (filledLengthInBytes / | ||||
| 							Format.nChannels / | ||||
| 							(uint) (Format.wBitsPerSample / 8)) | ||||
| 						) | ||||
| 					}; | ||||
| 				AudioBytes = (uint) filledLengthInBytes, | ||||
| 				pAudioData = (IntPtr) buffer, | ||||
| 				PlayLength = ( | ||||
| 					(uint) (filledLengthInBytes / | ||||
| 					Format.nChannels / | ||||
| 					(uint) (Format.wBitsPerSample / 8)) | ||||
| 				) | ||||
| 			}; | ||||
| 
 | ||||
| 					FAudio.FAudioSourceVoice_SubmitSourceBuffer( | ||||
| 						Handle, | ||||
| 						ref buf, | ||||
| 						IntPtr.Zero | ||||
| 					); | ||||
| 				} | ||||
| 			} | ||||
| 			FAudio.FAudioSourceVoice_SubmitSourceBuffer( | ||||
| 				Handle, | ||||
| 				ref buf, | ||||
| 				IntPtr.Zero | ||||
| 			); | ||||
| 
 | ||||
| 			queuedBufferCount += 1; | ||||
| 
 | ||||
| 			/* We have reached the end of the file, what do we do? */ | ||||
| 			if (reachedEnd) | ||||
|  | @ -169,9 +152,14 @@ namespace MoonWorks.Audio | |||
| 			out bool reachedEnd | ||||
| 		); | ||||
| 
 | ||||
| 		protected override void Destroy() | ||||
| 		protected unsafe override void Destroy() | ||||
| 		{ | ||||
| 			StopImmediate(); | ||||
| 
 | ||||
| 			for (int i = 0; i < BUFFER_COUNT; i += 1) | ||||
| 			{ | ||||
| 				NativeMemory.Free((void*) buffers[i]); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue