Formatting pass
							parent
							
								
									7a754e1c90
								
							
						
					
					
						commit
						26dc361d31
					
				
							
								
								
									
										444
									
								
								AudioDevice.cs
								
								
								
								
							
							
						
						
									
										444
									
								
								AudioDevice.cs
								
								
								
								
							|  | @ -1,277 +1,277 @@ | ||||||
| using System; | using System; | ||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
| using System.Runtime.InteropServices; | using System.Runtime.InteropServices; | ||||||
| 
 | 
 | ||||||
| namespace MoonWorks.Audio | namespace MoonWorks.Audio | ||||||
| { | { | ||||||
|     public class AudioDevice : IDisposable | 	public class AudioDevice : IDisposable | ||||||
|     { | 	{ | ||||||
|         public IntPtr Handle { get; } | 		public IntPtr Handle { get; } | ||||||
|         public byte[] Handle3D { get; } | 		public byte[] Handle3D { get; } | ||||||
|         public IntPtr MasteringVoice { get; } | 		public IntPtr MasteringVoice { get; } | ||||||
|         public FAudio.FAudioDeviceDetails DeviceDetails { get; } | 		public FAudio.FAudioDeviceDetails DeviceDetails { get; } | ||||||
|         public IntPtr ReverbVoice { get; } | 		public IntPtr ReverbVoice { get; } | ||||||
| 
 | 
 | ||||||
|         public float CurveDistanceScalar = 1f; | 		public float CurveDistanceScalar = 1f; | ||||||
|         public float DopplerScale = 1f; | 		public float DopplerScale = 1f; | ||||||
|         public float SpeedOfSound = 343.5f; | 		public float SpeedOfSound = 343.5f; | ||||||
| 
 | 
 | ||||||
|         internal FAudio.FAudioVoiceSends ReverbSends; | 		internal FAudio.FAudioVoiceSends ReverbSends; | ||||||
| 
 | 
 | ||||||
|         private readonly List<WeakReference<AudioResource>> resources = new List<WeakReference<AudioResource>>(); | 		private readonly List<WeakReference<AudioResource>> resources = new List<WeakReference<AudioResource>>(); | ||||||
|         private readonly List<WeakReference<StreamingSound>> streamingSounds = new List<WeakReference<StreamingSound>>(); | 		private readonly List<WeakReference<StreamingSound>> streamingSounds = new List<WeakReference<StreamingSound>>(); | ||||||
| 
 | 
 | ||||||
|         private bool IsDisposed; | 		private bool IsDisposed; | ||||||
| 
 | 
 | ||||||
|         public unsafe AudioDevice() | 		public unsafe AudioDevice() | ||||||
|         { | 		{ | ||||||
|             FAudio.FAudioCreate(out var handle, 0, 0); | 			FAudio.FAudioCreate(out var handle, 0, 0); | ||||||
|             Handle = handle; | 			Handle = handle; | ||||||
| 
 | 
 | ||||||
|             /* Find a suitable device */ | 			/* Find a suitable device */ | ||||||
| 
 | 
 | ||||||
|             FAudio.FAudio_GetDeviceCount(Handle, out var devices); | 			FAudio.FAudio_GetDeviceCount(Handle, out var devices); | ||||||
| 
 | 
 | ||||||
|             if (devices == 0) | 			if (devices == 0) | ||||||
|             { | 			{ | ||||||
|                 Logger.LogError("No audio devices found!"); | 				Logger.LogError("No audio devices found!"); | ||||||
|                 Handle = IntPtr.Zero; | 				Handle = IntPtr.Zero; | ||||||
|                 FAudio.FAudio_Release(Handle); | 				FAudio.FAudio_Release(Handle); | ||||||
|                 return; | 				return; | ||||||
|             } | 			} | ||||||
| 
 | 
 | ||||||
|             FAudio.FAudioDeviceDetails deviceDetails; | 			FAudio.FAudioDeviceDetails deviceDetails; | ||||||
| 
 | 
 | ||||||
|             uint i = 0; | 			uint i = 0; | ||||||
|             for (i = 0; i < devices; i++) | 			for (i = 0; i < devices; i++) | ||||||
|             { | 			{ | ||||||
|                 FAudio.FAudio_GetDeviceDetails( | 				FAudio.FAudio_GetDeviceDetails( | ||||||
|                     Handle, | 					Handle, | ||||||
|                     i, | 					i, | ||||||
|                     out deviceDetails | 					out deviceDetails | ||||||
|                 ); | 				); | ||||||
|                 if ((deviceDetails.Role & FAudio.FAudioDeviceRole.FAudioDefaultGameDevice) == FAudio.FAudioDeviceRole.FAudioDefaultGameDevice) | 				if ((deviceDetails.Role & FAudio.FAudioDeviceRole.FAudioDefaultGameDevice) == FAudio.FAudioDeviceRole.FAudioDefaultGameDevice) | ||||||
|                 { | 				{ | ||||||
|                     DeviceDetails = deviceDetails; | 					DeviceDetails = deviceDetails; | ||||||
|                     break; | 					break; | ||||||
|                 } | 				} | ||||||
|             } | 			} | ||||||
| 
 | 
 | ||||||
|             if (i == devices) | 			if (i == devices) | ||||||
|             { | 			{ | ||||||
|                 i = 0; /* whatever we'll just use the first one I guess */ | 				i = 0; /* whatever we'll just use the first one I guess */ | ||||||
|                 FAudio.FAudio_GetDeviceDetails( | 				FAudio.FAudio_GetDeviceDetails( | ||||||
|                     Handle, | 					Handle, | ||||||
|                     i, | 					i, | ||||||
|                     out deviceDetails | 					out deviceDetails | ||||||
|                 ); | 				); | ||||||
|                 DeviceDetails = deviceDetails; | 				DeviceDetails = deviceDetails; | ||||||
|             } | 			} | ||||||
| 
 | 
 | ||||||
|             /* Init Mastering Voice */ | 			/* Init Mastering Voice */ | ||||||
|             IntPtr masteringVoice; | 			IntPtr masteringVoice; | ||||||
| 
 | 
 | ||||||
|             if (FAudio.FAudio_CreateMasteringVoice( | 			if (FAudio.FAudio_CreateMasteringVoice( | ||||||
|                 Handle, | 				Handle, | ||||||
|                 out masteringVoice, | 				out masteringVoice, | ||||||
|                 FAudio.FAUDIO_DEFAULT_CHANNELS, | 				FAudio.FAUDIO_DEFAULT_CHANNELS, | ||||||
|                 FAudio.FAUDIO_DEFAULT_SAMPLERATE, | 				FAudio.FAUDIO_DEFAULT_SAMPLERATE, | ||||||
|                 0, | 				0, | ||||||
|                 i, | 				i, | ||||||
|                 IntPtr.Zero | 				IntPtr.Zero | ||||||
|             ) != 0) | 			) != 0) | ||||||
|             { | 			{ | ||||||
|                 Logger.LogError("No mastering voice found!"); | 				Logger.LogError("No mastering voice found!"); | ||||||
|                 Handle = IntPtr.Zero; | 				Handle = IntPtr.Zero; | ||||||
|                 FAudio.FAudio_Release(Handle); | 				FAudio.FAudio_Release(Handle); | ||||||
|                 return; | 				return; | ||||||
|             } | 			} | ||||||
| 
 | 
 | ||||||
|             MasteringVoice = masteringVoice; | 			MasteringVoice = masteringVoice; | ||||||
| 
 | 
 | ||||||
|             /* Init 3D Audio */ | 			/* Init 3D Audio */ | ||||||
| 
 | 
 | ||||||
|             Handle3D = new byte[FAudio.F3DAUDIO_HANDLE_BYTESIZE]; | 			Handle3D = new byte[FAudio.F3DAUDIO_HANDLE_BYTESIZE]; | ||||||
|             FAudio.F3DAudioInitialize( | 			FAudio.F3DAudioInitialize( | ||||||
|                 DeviceDetails.OutputFormat.dwChannelMask, | 				DeviceDetails.OutputFormat.dwChannelMask, | ||||||
|                 SpeedOfSound, | 				SpeedOfSound, | ||||||
|                 Handle3D | 				Handle3D | ||||||
|             ); | 			); | ||||||
| 
 | 
 | ||||||
|             /* Init reverb */ | 			/* Init reverb */ | ||||||
| 
 | 
 | ||||||
|             IntPtr reverbVoice; | 			IntPtr reverbVoice; | ||||||
| 
 | 
 | ||||||
|             IntPtr reverb; | 			IntPtr reverb; | ||||||
|             FAudio.FAudioCreateReverb(out reverb, 0); | 			FAudio.FAudioCreateReverb(out reverb, 0); | ||||||
| 
 | 
 | ||||||
|             IntPtr chainPtr; | 			IntPtr chainPtr; | ||||||
|             chainPtr = Marshal.AllocHGlobal( | 			chainPtr = Marshal.AllocHGlobal( | ||||||
|                 Marshal.SizeOf<FAudio.FAudioEffectChain>() | 				Marshal.SizeOf<FAudio.FAudioEffectChain>() | ||||||
|             ); | 			); | ||||||
| 
 | 
 | ||||||
|             FAudio.FAudioEffectChain* reverbChain = (FAudio.FAudioEffectChain*) chainPtr; | 			FAudio.FAudioEffectChain* reverbChain = (FAudio.FAudioEffectChain*) chainPtr; | ||||||
|             reverbChain->EffectCount = 1; | 			reverbChain->EffectCount = 1; | ||||||
|             reverbChain->pEffectDescriptors = Marshal.AllocHGlobal( | 			reverbChain->pEffectDescriptors = Marshal.AllocHGlobal( | ||||||
|                 Marshal.SizeOf<FAudio.FAudioEffectDescriptor>() | 				Marshal.SizeOf<FAudio.FAudioEffectDescriptor>() | ||||||
|             ); | 			); | ||||||
| 
 | 
 | ||||||
|             FAudio.FAudioEffectDescriptor* reverbDescriptor = | 			FAudio.FAudioEffectDescriptor* reverbDescriptor = | ||||||
|                 (FAudio.FAudioEffectDescriptor*) reverbChain->pEffectDescriptors; | 				(FAudio.FAudioEffectDescriptor*) reverbChain->pEffectDescriptors; | ||||||
| 
 | 
 | ||||||
|             reverbDescriptor->InitialState = 1; | 			reverbDescriptor->InitialState = 1; | ||||||
|             reverbDescriptor->OutputChannels = (uint) ( | 			reverbDescriptor->OutputChannels = (uint) ( | ||||||
|                 (DeviceDetails.OutputFormat.Format.nChannels == 6) ? 6 : 1 | 				(DeviceDetails.OutputFormat.Format.nChannels == 6) ? 6 : 1 | ||||||
|             ); | 			); | ||||||
|             reverbDescriptor->pEffect = reverb; | 			reverbDescriptor->pEffect = reverb; | ||||||
| 
 | 
 | ||||||
|             FAudio.FAudio_CreateSubmixVoice( | 			FAudio.FAudio_CreateSubmixVoice( | ||||||
|                 Handle, | 				Handle, | ||||||
|                 out reverbVoice, | 				out reverbVoice, | ||||||
|                 1, /* omnidirectional reverb */ | 				1, /* omnidirectional reverb */ | ||||||
|                 DeviceDetails.OutputFormat.Format.nSamplesPerSec, | 				DeviceDetails.OutputFormat.Format.nSamplesPerSec, | ||||||
|                 0, | 				0, | ||||||
|                 0, | 				0, | ||||||
|                 IntPtr.Zero, | 				IntPtr.Zero, | ||||||
|                 chainPtr | 				chainPtr | ||||||
|             ); | 			); | ||||||
|             FAudio.FAPOBase_Release(reverb); | 			FAudio.FAPOBase_Release(reverb); | ||||||
| 
 | 
 | ||||||
|             Marshal.FreeHGlobal(reverbChain->pEffectDescriptors); | 			Marshal.FreeHGlobal(reverbChain->pEffectDescriptors); | ||||||
|             Marshal.FreeHGlobal(chainPtr); | 			Marshal.FreeHGlobal(chainPtr); | ||||||
| 
 | 
 | ||||||
|             ReverbVoice = reverbVoice; | 			ReverbVoice = reverbVoice; | ||||||
| 
 | 
 | ||||||
|             /* Init reverb params */ | 			/* Init reverb params */ | ||||||
|             // Defaults based on FAUDIOFX_I3DL2_PRESET_GENERIC | 			// Defaults based on FAUDIOFX_I3DL2_PRESET_GENERIC | ||||||
| 
 | 
 | ||||||
|             IntPtr reverbParamsPtr = Marshal.AllocHGlobal( | 			IntPtr reverbParamsPtr = Marshal.AllocHGlobal( | ||||||
|                 Marshal.SizeOf<FAudio.FAudioFXReverbParameters>() | 				Marshal.SizeOf<FAudio.FAudioFXReverbParameters>() | ||||||
|             ); | 			); | ||||||
| 
 | 
 | ||||||
|             FAudio.FAudioFXReverbParameters* reverbParams = (FAudio.FAudioFXReverbParameters*) reverbParamsPtr; | 			FAudio.FAudioFXReverbParameters* reverbParams = (FAudio.FAudioFXReverbParameters*) reverbParamsPtr; | ||||||
|             reverbParams->WetDryMix = 100.0f; | 			reverbParams->WetDryMix = 100.0f; | ||||||
|             reverbParams->ReflectionsDelay = 7; | 			reverbParams->ReflectionsDelay = 7; | ||||||
|             reverbParams->ReverbDelay = 11; | 			reverbParams->ReverbDelay = 11; | ||||||
|             reverbParams->RearDelay = FAudio.FAUDIOFX_REVERB_DEFAULT_REAR_DELAY; | 			reverbParams->RearDelay = FAudio.FAUDIOFX_REVERB_DEFAULT_REAR_DELAY; | ||||||
|             reverbParams->PositionLeft = FAudio.FAUDIOFX_REVERB_DEFAULT_POSITION; | 			reverbParams->PositionLeft = FAudio.FAUDIOFX_REVERB_DEFAULT_POSITION; | ||||||
|             reverbParams->PositionRight = FAudio.FAUDIOFX_REVERB_DEFAULT_POSITION; | 			reverbParams->PositionRight = FAudio.FAUDIOFX_REVERB_DEFAULT_POSITION; | ||||||
|             reverbParams->PositionMatrixLeft = FAudio.FAUDIOFX_REVERB_DEFAULT_POSITION_MATRIX; | 			reverbParams->PositionMatrixLeft = FAudio.FAUDIOFX_REVERB_DEFAULT_POSITION_MATRIX; | ||||||
|             reverbParams->PositionMatrixRight = FAudio.FAUDIOFX_REVERB_DEFAULT_POSITION_MATRIX; | 			reverbParams->PositionMatrixRight = FAudio.FAUDIOFX_REVERB_DEFAULT_POSITION_MATRIX; | ||||||
|             reverbParams->EarlyDiffusion = 15; | 			reverbParams->EarlyDiffusion = 15; | ||||||
|             reverbParams->LateDiffusion = 15; | 			reverbParams->LateDiffusion = 15; | ||||||
|             reverbParams->LowEQGain = 8; | 			reverbParams->LowEQGain = 8; | ||||||
|             reverbParams->LowEQCutoff = 4; | 			reverbParams->LowEQCutoff = 4; | ||||||
|             reverbParams->HighEQGain = 8; | 			reverbParams->HighEQGain = 8; | ||||||
|             reverbParams->HighEQCutoff = 6; | 			reverbParams->HighEQCutoff = 6; | ||||||
|             reverbParams->RoomFilterFreq = 5000f; | 			reverbParams->RoomFilterFreq = 5000f; | ||||||
|             reverbParams->RoomFilterMain = -10f; | 			reverbParams->RoomFilterMain = -10f; | ||||||
|             reverbParams->RoomFilterHF = -1f; | 			reverbParams->RoomFilterHF = -1f; | ||||||
|             reverbParams->ReflectionsGain = -26.0200005f; | 			reverbParams->ReflectionsGain = -26.0200005f; | ||||||
|             reverbParams->ReverbGain = 10.0f; | 			reverbParams->ReverbGain = 10.0f; | ||||||
|             reverbParams->DecayTime = 1.49000001f; | 			reverbParams->DecayTime = 1.49000001f; | ||||||
|             reverbParams->Density = 100.0f; | 			reverbParams->Density = 100.0f; | ||||||
|             reverbParams->RoomSize = FAudio.FAUDIOFX_REVERB_DEFAULT_ROOM_SIZE; | 			reverbParams->RoomSize = FAudio.FAUDIOFX_REVERB_DEFAULT_ROOM_SIZE; | ||||||
|             FAudio.FAudioVoice_SetEffectParameters( | 			FAudio.FAudioVoice_SetEffectParameters( | ||||||
|                 ReverbVoice, | 				ReverbVoice, | ||||||
|                 0, | 				0, | ||||||
|                 reverbParamsPtr, | 				reverbParamsPtr, | ||||||
|                 (uint) Marshal.SizeOf<FAudio.FAudioFXReverbParameters>(), | 				(uint) Marshal.SizeOf<FAudio.FAudioFXReverbParameters>(), | ||||||
|                 0 | 				0 | ||||||
|             ); | 			); | ||||||
|             Marshal.FreeHGlobal(reverbParamsPtr); | 			Marshal.FreeHGlobal(reverbParamsPtr); | ||||||
| 
 | 
 | ||||||
|             /* Init reverb sends */ | 			/* Init reverb sends */ | ||||||
| 
 | 
 | ||||||
|             ReverbSends = new FAudio.FAudioVoiceSends | 			ReverbSends = new FAudio.FAudioVoiceSends | ||||||
|             { | 			{ | ||||||
|                 SendCount = 2, | 				SendCount = 2, | ||||||
|                 pSends = Marshal.AllocHGlobal( | 				pSends = Marshal.AllocHGlobal( | ||||||
|                     2 * Marshal.SizeOf<FAudio.FAudioSendDescriptor>() | 					2 * Marshal.SizeOf<FAudio.FAudioSendDescriptor>() | ||||||
|                 ) | 				) | ||||||
|             }; | 			}; | ||||||
|             FAudio.FAudioSendDescriptor* sendDesc = (FAudio.FAudioSendDescriptor*) ReverbSends.pSends; | 			FAudio.FAudioSendDescriptor* sendDesc = (FAudio.FAudioSendDescriptor*) ReverbSends.pSends; | ||||||
|             sendDesc[0].Flags = 0; | 			sendDesc[0].Flags = 0; | ||||||
|             sendDesc[0].pOutputVoice = MasteringVoice; | 			sendDesc[0].pOutputVoice = MasteringVoice; | ||||||
|             sendDesc[1].Flags = 0; | 			sendDesc[1].Flags = 0; | ||||||
|             sendDesc[1].pOutputVoice = ReverbVoice; | 			sendDesc[1].pOutputVoice = ReverbVoice; | ||||||
|         } | 		} | ||||||
| 
 | 
 | ||||||
|         public void Update() | 		public void Update() | ||||||
|         { | 		{ | ||||||
|             for (var i = streamingSounds.Count - 1; i >= 0; i--) | 			for (var i = streamingSounds.Count - 1; i >= 0; i--) | ||||||
|             { | 			{ | ||||||
|                 var weakReference = streamingSounds[i]; | 				var weakReference = streamingSounds[i]; | ||||||
|                 if (weakReference.TryGetTarget(out var streamingSound)) | 				if (weakReference.TryGetTarget(out var streamingSound)) | ||||||
|                 { | 				{ | ||||||
|                     streamingSound.Update(); | 					streamingSound.Update(); | ||||||
|                 } | 				} | ||||||
|                 else | 				else | ||||||
|                 { | 				{ | ||||||
|                     streamingSounds.RemoveAt(i); | 					streamingSounds.RemoveAt(i); | ||||||
|                 } | 				} | ||||||
|             } | 			} | ||||||
|         } | 		} | ||||||
| 
 | 
 | ||||||
|         internal void AddDynamicSoundInstance(StreamingSound instance) | 		internal void AddDynamicSoundInstance(StreamingSound instance) | ||||||
|         { | 		{ | ||||||
|             streamingSounds.Add(new WeakReference<StreamingSound>(instance)); | 			streamingSounds.Add(new WeakReference<StreamingSound>(instance)); | ||||||
|         } | 		} | ||||||
| 
 | 
 | ||||||
|         internal void AddResourceReference(WeakReference<AudioResource> resourceReference) | 		internal void AddResourceReference(WeakReference<AudioResource> resourceReference) | ||||||
|         { | 		{ | ||||||
|             lock (resources) | 			lock (resources) | ||||||
|             { | 			{ | ||||||
|                 resources.Add(resourceReference); | 				resources.Add(resourceReference); | ||||||
|             } | 			} | ||||||
|         } | 		} | ||||||
| 
 | 
 | ||||||
|         internal void RemoveResourceReference(WeakReference<AudioResource> resourceReference) | 		internal void RemoveResourceReference(WeakReference<AudioResource> resourceReference) | ||||||
|         { | 		{ | ||||||
|             lock (resources) | 			lock (resources) | ||||||
|             { | 			{ | ||||||
|                 resources.Remove(resourceReference); | 				resources.Remove(resourceReference); | ||||||
|             } | 			} | ||||||
|         } | 		} | ||||||
| 
 | 
 | ||||||
|         protected virtual void Dispose(bool disposing) | 		protected virtual void Dispose(bool disposing) | ||||||
|         { | 		{ | ||||||
|             if (!IsDisposed) | 			if (!IsDisposed) | ||||||
|             { | 			{ | ||||||
|                 if (disposing) | 				if (disposing) | ||||||
|                 { | 				{ | ||||||
| 					for (var i = streamingSounds.Count - 1; i >= 0; i--) | 					for (var i = streamingSounds.Count - 1; i >= 0; i--) | ||||||
| 					{ | 					{ | ||||||
| 						var weakReference = streamingSounds[i]; | 						var weakReference = streamingSounds[i]; | ||||||
| 
 | 
 | ||||||
| 						if (weakReference.TryGetTarget(out var streamingSound)) | 						if (weakReference.TryGetTarget(out var streamingSound)) | ||||||
|                         { | 						{ | ||||||
|                             streamingSound.Dispose(); | 							streamingSound.Dispose(); | ||||||
|                         } | 						} | ||||||
| 					} | 					} | ||||||
| 					streamingSounds.Clear(); | 					streamingSounds.Clear(); | ||||||
|                 } | 				} | ||||||
| 
 | 
 | ||||||
| 				FAudio.FAudioVoice_DestroyVoice(ReverbVoice); | 				FAudio.FAudioVoice_DestroyVoice(ReverbVoice); | ||||||
| 				FAudio.FAudioVoice_DestroyVoice(MasteringVoice); | 				FAudio.FAudioVoice_DestroyVoice(MasteringVoice); | ||||||
|                 FAudio.FAudio_Release(Handle); | 				FAudio.FAudio_Release(Handle); | ||||||
| 
 | 
 | ||||||
|                 IsDisposed = true; | 				IsDisposed = true; | ||||||
|             } | 			} | ||||||
|         } | 		} | ||||||
| 
 | 
 | ||||||
|         // TODO: override finalizer only if 'Dispose(bool disposing)' has code to free unmanaged resources | 		// TODO: override finalizer only if 'Dispose(bool disposing)' has code to free unmanaged resources | ||||||
|         ~AudioDevice() | 		~AudioDevice() | ||||||
|         { | 		{ | ||||||
|             // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method | 			// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method | ||||||
|             Dispose(disposing: false); | 			Dispose(disposing: false); | ||||||
|         } | 		} | ||||||
| 
 | 
 | ||||||
|         public void Dispose() | 		public void Dispose() | ||||||
|         { | 		{ | ||||||
|             // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method | 			// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method | ||||||
|             Dispose(disposing: true); | 			Dispose(disposing: true); | ||||||
|             GC.SuppressFinalize(this); | 			GC.SuppressFinalize(this); | ||||||
|         } | 		} | ||||||
|     } | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,12 +1,12 @@ | ||||||
| using System; | using System; | ||||||
| using System.Runtime.InteropServices; | using System.Runtime.InteropServices; | ||||||
| using MoonWorks.Math; | using MoonWorks.Math; | ||||||
| 
 | 
 | ||||||
| namespace MoonWorks.Audio | namespace MoonWorks.Audio | ||||||
| { | { | ||||||
|     public class AudioEmitter : AudioResource | 	public class AudioEmitter : AudioResource | ||||||
|     { | 	{ | ||||||
|         internal FAudio.F3DAUDIO_EMITTER emitterData; | 		internal FAudio.F3DAUDIO_EMITTER emitterData; | ||||||
| 
 | 
 | ||||||
| 		public float DopplerScale | 		public float DopplerScale | ||||||
| 		{ | 		{ | ||||||
|  | @ -107,17 +107,17 @@ namespace MoonWorks.Audio | ||||||
| 			GCHandleType.Pinned | 			GCHandleType.Pinned | ||||||
| 		); | 		); | ||||||
| 
 | 
 | ||||||
|         public AudioEmitter(AudioDevice device) : base(device) | 		public AudioEmitter(AudioDevice device) : base(device) | ||||||
|         { | 		{ | ||||||
|             emitterData = new FAudio.F3DAUDIO_EMITTER(); | 			emitterData = new FAudio.F3DAUDIO_EMITTER(); | ||||||
| 
 | 
 | ||||||
|             DopplerScale = 1f; | 			DopplerScale = 1f; | ||||||
|             Forward = Vector3.Forward; | 			Forward = Vector3.Forward; | ||||||
|             Position = Vector3.Zero; | 			Position = Vector3.Zero; | ||||||
|             Up = Vector3.Up; | 			Up = Vector3.Up; | ||||||
|             Velocity = Vector3.Zero; | 			Velocity = Vector3.Zero; | ||||||
| 
 | 
 | ||||||
|             /* Unexposed variables, defaults based on XNA behavior */ | 			/* Unexposed variables, defaults based on XNA behavior */ | ||||||
| 			emitterData.pCone = IntPtr.Zero; | 			emitterData.pCone = IntPtr.Zero; | ||||||
| 			emitterData.ChannelCount = 1; | 			emitterData.ChannelCount = 1; | ||||||
| 			emitterData.ChannelRadius = 1.0f; | 			emitterData.ChannelRadius = 1.0f; | ||||||
|  | @ -128,8 +128,8 @@ namespace MoonWorks.Audio | ||||||
| 			emitterData.pLPFReverbCurve = IntPtr.Zero; | 			emitterData.pLPFReverbCurve = IntPtr.Zero; | ||||||
| 			emitterData.pReverbCurve = IntPtr.Zero; | 			emitterData.pReverbCurve = IntPtr.Zero; | ||||||
| 			emitterData.CurveDistanceScaler = 1.0f; | 			emitterData.CurveDistanceScaler = 1.0f; | ||||||
|         } | 		} | ||||||
| 
 | 
 | ||||||
|         protected override void Destroy() { } | 		protected override void Destroy() { } | ||||||
|     } | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,11 +1,11 @@ | ||||||
| using System; | using System; | ||||||
| using MoonWorks.Math; | using MoonWorks.Math; | ||||||
| 
 | 
 | ||||||
| namespace MoonWorks.Audio | namespace MoonWorks.Audio | ||||||
| { | { | ||||||
|     public class AudioListener : AudioResource | 	public class AudioListener : AudioResource | ||||||
|     { | 	{ | ||||||
|         internal FAudio.F3DAUDIO_LISTENER listenerData; | 		internal FAudio.F3DAUDIO_LISTENER listenerData; | ||||||
| 
 | 
 | ||||||
| 		public Vector3 Forward | 		public Vector3 Forward | ||||||
| 		{ | 		{ | ||||||
|  | @ -80,18 +80,18 @@ namespace MoonWorks.Audio | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|         public AudioListener(AudioDevice device) : base(device) | 		public AudioListener(AudioDevice device) : base(device) | ||||||
|         { | 		{ | ||||||
|             listenerData = new FAudio.F3DAUDIO_LISTENER(); | 			listenerData = new FAudio.F3DAUDIO_LISTENER(); | ||||||
|             Forward = Vector3.Forward; | 			Forward = Vector3.Forward; | ||||||
|             Position = Vector3.Zero; | 			Position = Vector3.Zero; | ||||||
|             Up = Vector3.Up; | 			Up = Vector3.Up; | ||||||
|             Velocity = Vector3.Zero; | 			Velocity = Vector3.Zero; | ||||||
| 
 | 
 | ||||||
|             /* Unexposed variables, defaults based on XNA behavior */ | 			/* Unexposed variables, defaults based on XNA behavior */ | ||||||
| 			listenerData.pCone = IntPtr.Zero; | 			listenerData.pCone = IntPtr.Zero; | ||||||
|         } | 		} | ||||||
| 
 | 
 | ||||||
|         protected override void Destroy() { } | 		protected override void Destroy() { } | ||||||
|     } | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,52 +1,52 @@ | ||||||
| using System; | using System; | ||||||
| 
 | 
 | ||||||
| namespace MoonWorks.Audio | namespace MoonWorks.Audio | ||||||
| { | { | ||||||
|     public abstract class AudioResource : IDisposable | 	public abstract class AudioResource : IDisposable | ||||||
|     { | 	{ | ||||||
|         public AudioDevice Device { get; } | 		public AudioDevice Device { get; } | ||||||
| 
 | 
 | ||||||
|         public bool IsDisposed { get; private set; } | 		public bool IsDisposed { get; private set; } | ||||||
| 
 | 
 | ||||||
|         private WeakReference<AudioResource> selfReference; | 		private WeakReference<AudioResource> selfReference; | ||||||
| 
 | 
 | ||||||
|         public AudioResource(AudioDevice device) | 		public AudioResource(AudioDevice device) | ||||||
|         { | 		{ | ||||||
|             Device = device; | 			Device = device; | ||||||
| 
 | 
 | ||||||
|             selfReference = new WeakReference<AudioResource>(this); | 			selfReference = new WeakReference<AudioResource>(this); | ||||||
|             Device.AddResourceReference(selfReference); | 			Device.AddResourceReference(selfReference); | ||||||
|         } | 		} | ||||||
| 
 | 
 | ||||||
|         protected abstract void Destroy(); | 		protected abstract void Destroy(); | ||||||
| 
 | 
 | ||||||
|         protected virtual void Dispose(bool disposing) | 		protected virtual void Dispose(bool disposing) | ||||||
|         { | 		{ | ||||||
|             if (!IsDisposed) | 			if (!IsDisposed) | ||||||
|             { | 			{ | ||||||
|                 Destroy(); | 				Destroy(); | ||||||
| 
 | 
 | ||||||
|                 if (selfReference != null) | 				if (selfReference != null) | ||||||
|                 { | 				{ | ||||||
|                     Device.RemoveResourceReference(selfReference); | 					Device.RemoveResourceReference(selfReference); | ||||||
|                     selfReference = null; | 					selfReference = null; | ||||||
|                 } | 				} | ||||||
| 
 | 
 | ||||||
|                 IsDisposed = true; | 				IsDisposed = true; | ||||||
|             } | 			} | ||||||
|         } | 		} | ||||||
| 
 | 
 | ||||||
|         ~AudioResource() | 		~AudioResource() | ||||||
|         { | 		{ | ||||||
|             // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method | 			// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method | ||||||
|             Dispose(disposing: false); | 			Dispose(disposing: false); | ||||||
|         } | 		} | ||||||
| 
 | 
 | ||||||
|         public void Dispose() | 		public void Dispose() | ||||||
|         { | 		{ | ||||||
|             // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method | 			// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method | ||||||
|             Dispose(disposing: true); | 			Dispose(disposing: true); | ||||||
|             GC.SuppressFinalize(this); | 			GC.SuppressFinalize(this); | ||||||
|         } | 		} | ||||||
|     } | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
							
								
								
									
										486
									
								
								SoundInstance.cs
								
								
								
								
							
							
						
						
									
										486
									
								
								SoundInstance.cs
								
								
								
								
							|  | @ -1,271 +1,271 @@ | ||||||
| using System; | using System; | ||||||
| using System.Runtime.InteropServices; | using System.Runtime.InteropServices; | ||||||
| using MoonWorks.Math; | using MoonWorks.Math; | ||||||
| 
 | 
 | ||||||
| namespace MoonWorks.Audio | namespace MoonWorks.Audio | ||||||
| { | { | ||||||
|     public abstract class SoundInstance : AudioResource | 	public abstract class SoundInstance : AudioResource | ||||||
|     { | 	{ | ||||||
|         internal IntPtr Handle { get; } | 		internal IntPtr Handle { get; } | ||||||
|         internal FAudio.FAudioWaveFormatEx Format { get; } | 		internal FAudio.FAudioWaveFormatEx Format { get; } | ||||||
|         public bool Loop { get; } | 		public bool Loop { get; } | ||||||
| 
 | 
 | ||||||
|         protected FAudio.F3DAUDIO_DSP_SETTINGS dspSettings; | 		protected FAudio.F3DAUDIO_DSP_SETTINGS dspSettings; | ||||||
| 
 | 
 | ||||||
|         protected bool is3D; | 		protected bool is3D; | ||||||
| 
 | 
 | ||||||
|         public abstract SoundState State { get; protected set; } | 		public abstract SoundState State { get; protected set; } | ||||||
| 
 | 
 | ||||||
|         private float _pan = 0; | 		private float _pan = 0; | ||||||
|         public float Pan | 		public float Pan | ||||||
|         { | 		{ | ||||||
|             get => _pan; | 			get => _pan; | ||||||
|             set | 			set | ||||||
|             { | 			{ | ||||||
|                 _pan = value; | 				_pan = value; | ||||||
| 
 | 
 | ||||||
|                 if (_pan < -1f) | 				if (_pan < -1f) | ||||||
|                 { | 				{ | ||||||
|                     _pan = -1f; | 					_pan = -1f; | ||||||
|                 } | 				} | ||||||
|                 if (_pan > 1f) | 				if (_pan > 1f) | ||||||
|                 { | 				{ | ||||||
|                     _pan = 1f; | 					_pan = 1f; | ||||||
|                 } | 				} | ||||||
| 
 | 
 | ||||||
|                 if (is3D) { return; } | 				if (is3D) { return; } | ||||||
| 
 | 
 | ||||||
|                 SetPanMatrixCoefficients(); | 				SetPanMatrixCoefficients(); | ||||||
|                 FAudio.FAudioVoice_SetOutputMatrix( | 				FAudio.FAudioVoice_SetOutputMatrix( | ||||||
|                     Handle, | 					Handle, | ||||||
|                     Device.MasteringVoice, | 					Device.MasteringVoice, | ||||||
|                     dspSettings.SrcChannelCount, | 					dspSettings.SrcChannelCount, | ||||||
|                     dspSettings.DstChannelCount, | 					dspSettings.DstChannelCount, | ||||||
|                     dspSettings.pMatrixCoefficients, | 					dspSettings.pMatrixCoefficients, | ||||||
|                     0 | 					0 | ||||||
|                 ); | 				); | ||||||
|             } | 			} | ||||||
|         } | 		} | ||||||
| 
 | 
 | ||||||
|         private float _pitch = 1; | 		private float _pitch = 1; | ||||||
|         public float Pitch | 		public float Pitch | ||||||
|         { | 		{ | ||||||
|             get => _pitch; | 			get => _pitch; | ||||||
|             set | 			set | ||||||
|             { | 			{ | ||||||
|                 _pitch = MathHelper.Clamp(value, -1f, 1f); | 				_pitch = MathHelper.Clamp(value, -1f, 1f); | ||||||
|                 UpdatePitch(); | 				UpdatePitch(); | ||||||
|             } | 			} | ||||||
|         } | 		} | ||||||
| 
 | 
 | ||||||
|         private float _volume = 1; | 		private float _volume = 1; | ||||||
|         public float Volume | 		public float Volume | ||||||
|         { | 		{ | ||||||
|             get => _volume; | 			get => _volume; | ||||||
|             set | 			set | ||||||
|             { | 			{ | ||||||
|                 _volume = value; | 				_volume = value; | ||||||
|                 FAudio.FAudioVoice_SetVolume(Handle, _volume, 0); | 				FAudio.FAudioVoice_SetVolume(Handle, _volume, 0); | ||||||
|             } | 			} | ||||||
|         } | 		} | ||||||
| 
 | 
 | ||||||
|         private float _reverb; | 		private float _reverb; | ||||||
|         public unsafe float Reverb | 		public unsafe float Reverb | ||||||
|         { | 		{ | ||||||
|             get => _reverb; | 			get => _reverb; | ||||||
|             set | 			set | ||||||
|             { | 			{ | ||||||
|                 _reverb = value; | 				_reverb = value; | ||||||
| 
 | 
 | ||||||
|                 float* outputMatrix = (float*) dspSettings.pMatrixCoefficients; | 				float* outputMatrix = (float*) dspSettings.pMatrixCoefficients; | ||||||
|                 outputMatrix[0] = _reverb; | 				outputMatrix[0] = _reverb; | ||||||
|                 if (dspSettings.SrcChannelCount == 2) | 				if (dspSettings.SrcChannelCount == 2) | ||||||
|                 { | 				{ | ||||||
|                     outputMatrix[1] = _reverb; | 					outputMatrix[1] = _reverb; | ||||||
|                 } | 				} | ||||||
| 
 | 
 | ||||||
|                 FAudio.FAudioVoice_SetOutputMatrix( | 				FAudio.FAudioVoice_SetOutputMatrix( | ||||||
|                     Handle, | 					Handle, | ||||||
|                     Device.ReverbVoice, | 					Device.ReverbVoice, | ||||||
|                     dspSettings.SrcChannelCount, | 					dspSettings.SrcChannelCount, | ||||||
|                     1, | 					1, | ||||||
|                     dspSettings.pMatrixCoefficients, | 					dspSettings.pMatrixCoefficients, | ||||||
|                     0 | 					0 | ||||||
|                 ); | 				); | ||||||
|             } | 			} | ||||||
|         } | 		} | ||||||
| 
 | 
 | ||||||
|         private float _lowPassFilter; | 		private float _lowPassFilter; | ||||||
|         public float LowPassFilter | 		public float LowPassFilter | ||||||
|         { | 		{ | ||||||
|             get => _lowPassFilter; | 			get => _lowPassFilter; | ||||||
|             set | 			set | ||||||
|             { | 			{ | ||||||
|                 _lowPassFilter = value; | 				_lowPassFilter = value; | ||||||
| 
 | 
 | ||||||
|                 FAudio.FAudioFilterParameters p = new FAudio.FAudioFilterParameters | 				FAudio.FAudioFilterParameters p = new FAudio.FAudioFilterParameters | ||||||
|                 { | 				{ | ||||||
|                     Type = FAudio.FAudioFilterType.FAudioLowPassFilter, | 					Type = FAudio.FAudioFilterType.FAudioLowPassFilter, | ||||||
|                     Frequency = _lowPassFilter, | 					Frequency = _lowPassFilter, | ||||||
|                     OneOverQ = 1f | 					OneOverQ = 1f | ||||||
|                 }; | 				}; | ||||||
|                 FAudio.FAudioVoice_SetFilterParameters( | 				FAudio.FAudioVoice_SetFilterParameters( | ||||||
|                     Handle, | 					Handle, | ||||||
|                     ref p, | 					ref p, | ||||||
|                     0 | 					0 | ||||||
|                 ); | 				); | ||||||
|             } | 			} | ||||||
|         } | 		} | ||||||
| 
 | 
 | ||||||
|         private float _highPassFilter; | 		private float _highPassFilter; | ||||||
|         public float HighPassFilter | 		public float HighPassFilter | ||||||
|         { | 		{ | ||||||
|             get => _highPassFilter; | 			get => _highPassFilter; | ||||||
|             set | 			set | ||||||
|             { | 			{ | ||||||
|                 _highPassFilter = value; | 				_highPassFilter = value; | ||||||
| 
 | 
 | ||||||
|                 FAudio.FAudioFilterParameters p = new FAudio.FAudioFilterParameters | 				FAudio.FAudioFilterParameters p = new FAudio.FAudioFilterParameters | ||||||
|                 { | 				{ | ||||||
|                     Type = FAudio.FAudioFilterType.FAudioHighPassFilter, | 					Type = FAudio.FAudioFilterType.FAudioHighPassFilter, | ||||||
|                     Frequency = _highPassFilter, | 					Frequency = _highPassFilter, | ||||||
|                     OneOverQ = 1f | 					OneOverQ = 1f | ||||||
|                 }; | 				}; | ||||||
|                 FAudio.FAudioVoice_SetFilterParameters( | 				FAudio.FAudioVoice_SetFilterParameters( | ||||||
|                     Handle, | 					Handle, | ||||||
|                     ref p, | 					ref p, | ||||||
|                     0 | 					0 | ||||||
|                 ); | 				); | ||||||
|             } | 			} | ||||||
|         } | 		} | ||||||
| 
 | 
 | ||||||
|         private float _bandPassFilter; | 		private float _bandPassFilter; | ||||||
|         public float BandPassFilter | 		public float BandPassFilter | ||||||
|         { | 		{ | ||||||
|             get => _bandPassFilter; | 			get => _bandPassFilter; | ||||||
|             set | 			set | ||||||
|             { | 			{ | ||||||
|                 _bandPassFilter = value; | 				_bandPassFilter = value; | ||||||
| 
 | 
 | ||||||
|                 FAudio.FAudioFilterParameters p = new FAudio.FAudioFilterParameters | 				FAudio.FAudioFilterParameters p = new FAudio.FAudioFilterParameters | ||||||
|                 { | 				{ | ||||||
|                     Type = FAudio.FAudioFilterType.FAudioBandPassFilter, | 					Type = FAudio.FAudioFilterType.FAudioBandPassFilter, | ||||||
|                     Frequency = _bandPassFilter, | 					Frequency = _bandPassFilter, | ||||||
|                     OneOverQ = 1f | 					OneOverQ = 1f | ||||||
|                 }; | 				}; | ||||||
|                 FAudio.FAudioVoice_SetFilterParameters( | 				FAudio.FAudioVoice_SetFilterParameters( | ||||||
|                     Handle, | 					Handle, | ||||||
|                     ref p, | 					ref p, | ||||||
|                     0 | 					0 | ||||||
|                 ); | 				); | ||||||
|             } | 			} | ||||||
|         } | 		} | ||||||
| 
 | 
 | ||||||
|         public SoundInstance( | 		public SoundInstance( | ||||||
|             AudioDevice device, | 			AudioDevice device, | ||||||
|             ushort channels, | 			ushort channels, | ||||||
|             uint samplesPerSecond, | 			uint samplesPerSecond, | ||||||
|             bool is3D, | 			bool is3D, | ||||||
|             bool loop | 			bool loop | ||||||
|         ) : base(device) | 		) : base(device) | ||||||
|         { | 		{ | ||||||
|             var blockAlign = (ushort)(4 * channels); | 			var blockAlign = (ushort) (4 * channels); | ||||||
|             var format = new FAudio.FAudioWaveFormatEx | 			var format = new FAudio.FAudioWaveFormatEx | ||||||
|             { | 			{ | ||||||
|                 wFormatTag = 3, | 				wFormatTag = 3, | ||||||
|                 wBitsPerSample = 32, | 				wBitsPerSample = 32, | ||||||
|                 nChannels = channels, | 				nChannels = channels, | ||||||
|                 nBlockAlign = blockAlign, | 				nBlockAlign = blockAlign, | ||||||
|                 nSamplesPerSec = samplesPerSecond, | 				nSamplesPerSec = samplesPerSecond, | ||||||
|                 nAvgBytesPerSec = blockAlign * samplesPerSecond | 				nAvgBytesPerSec = blockAlign * samplesPerSecond | ||||||
|             }; | 			}; | ||||||
| 
 | 
 | ||||||
|             Format = format; | 			Format = format; | ||||||
| 
 | 
 | ||||||
|             FAudio.FAudio_CreateSourceVoice( | 			FAudio.FAudio_CreateSourceVoice( | ||||||
|                 Device.Handle, | 				Device.Handle, | ||||||
|                 out var handle, | 				out var handle, | ||||||
|                 ref format, | 				ref format, | ||||||
|                 FAudio.FAUDIO_VOICE_USEFILTER, | 				FAudio.FAUDIO_VOICE_USEFILTER, | ||||||
|                 FAudio.FAUDIO_DEFAULT_FREQ_RATIO, | 				FAudio.FAUDIO_DEFAULT_FREQ_RATIO, | ||||||
|                 IntPtr.Zero, | 				IntPtr.Zero, | ||||||
|                 IntPtr.Zero, | 				IntPtr.Zero, | ||||||
|                 IntPtr.Zero | 				IntPtr.Zero | ||||||
|             ); | 			); | ||||||
| 
 | 
 | ||||||
|             if (handle == IntPtr.Zero) | 			if (handle == IntPtr.Zero) | ||||||
|             { | 			{ | ||||||
|                 Logger.LogError("SoundInstance failed to initialize!"); | 				Logger.LogError("SoundInstance failed to initialize!"); | ||||||
|                 return; | 				return; | ||||||
|             } | 			} | ||||||
| 
 | 
 | ||||||
|             Handle = handle; | 			Handle = handle; | ||||||
|             this.is3D = is3D; | 			this.is3D = is3D; | ||||||
|             InitDSPSettings(Format.nChannels); | 			InitDSPSettings(Format.nChannels); | ||||||
| 
 | 
 | ||||||
|             FAudio.FAudioVoice_SetOutputVoices( | 			FAudio.FAudioVoice_SetOutputVoices( | ||||||
|                 handle, | 				handle, | ||||||
|                 ref Device.ReverbSends | 				ref Device.ReverbSends | ||||||
|             ); | 			); | ||||||
| 
 | 
 | ||||||
|             Loop = loop; | 			Loop = loop; | ||||||
|             State = SoundState.Stopped; | 			State = SoundState.Stopped; | ||||||
|         } | 		} | ||||||
| 
 | 
 | ||||||
|         public void Apply3D(AudioListener listener, AudioEmitter emitter) | 		public void Apply3D(AudioListener listener, AudioEmitter emitter) | ||||||
|         { | 		{ | ||||||
|             is3D = true; | 			is3D = true; | ||||||
| 
 | 
 | ||||||
|             emitter.emitterData.CurveDistanceScaler = Device.CurveDistanceScalar; | 			emitter.emitterData.CurveDistanceScaler = Device.CurveDistanceScalar; | ||||||
|             emitter.emitterData.ChannelCount = dspSettings.SrcChannelCount; | 			emitter.emitterData.ChannelCount = dspSettings.SrcChannelCount; | ||||||
| 
 | 
 | ||||||
|             FAudio.F3DAudioCalculate( | 			FAudio.F3DAudioCalculate( | ||||||
|                 Device.Handle3D, | 				Device.Handle3D, | ||||||
|                 ref listener.listenerData, | 				ref listener.listenerData, | ||||||
|                 ref emitter.emitterData, | 				ref emitter.emitterData, | ||||||
|                 FAudio.F3DAUDIO_CALCULATE_MATRIX | FAudio.F3DAUDIO_CALCULATE_DOPPLER, | 				FAudio.F3DAUDIO_CALCULATE_MATRIX | FAudio.F3DAUDIO_CALCULATE_DOPPLER, | ||||||
|                 ref dspSettings | 				ref dspSettings | ||||||
|             ); | 			); | ||||||
| 
 | 
 | ||||||
|             UpdatePitch(); | 			UpdatePitch(); | ||||||
|             FAudio.FAudioVoice_SetOutputMatrix( | 			FAudio.FAudioVoice_SetOutputMatrix( | ||||||
|                 Handle, | 				Handle, | ||||||
|                 Device.MasteringVoice, | 				Device.MasteringVoice, | ||||||
|                 dspSettings.SrcChannelCount, | 				dspSettings.SrcChannelCount, | ||||||
|                 dspSettings.DstChannelCount, | 				dspSettings.DstChannelCount, | ||||||
|                 dspSettings.pMatrixCoefficients, | 				dspSettings.pMatrixCoefficients, | ||||||
|                 0 | 				0 | ||||||
|             ); | 			); | ||||||
|         } | 		} | ||||||
| 
 | 
 | ||||||
|         public abstract void Play(); | 		public abstract void Play(); | ||||||
|         public abstract void Pause(); | 		public abstract void Pause(); | ||||||
|         public abstract void Stop(bool immediate); | 		public abstract void Stop(bool immediate); | ||||||
| 
 | 
 | ||||||
|         private void InitDSPSettings(uint srcChannels) | 		private void InitDSPSettings(uint srcChannels) | ||||||
|         { | 		{ | ||||||
|             dspSettings = new FAudio.F3DAUDIO_DSP_SETTINGS(); | 			dspSettings = new FAudio.F3DAUDIO_DSP_SETTINGS(); | ||||||
|             dspSettings.DopplerFactor = 1f; | 			dspSettings.DopplerFactor = 1f; | ||||||
|             dspSettings.SrcChannelCount = srcChannels; | 			dspSettings.SrcChannelCount = srcChannels; | ||||||
|             dspSettings.DstChannelCount = Device.DeviceDetails.OutputFormat.Format.nChannels; | 			dspSettings.DstChannelCount = Device.DeviceDetails.OutputFormat.Format.nChannels; | ||||||
| 
 | 
 | ||||||
|             int memsize = ( | 			int memsize = ( | ||||||
|                 4 * | 				4 * | ||||||
|                 (int) dspSettings.SrcChannelCount * | 				(int) dspSettings.SrcChannelCount * | ||||||
|                 (int) dspSettings.DstChannelCount | 				(int) dspSettings.DstChannelCount | ||||||
|             ); | 			); | ||||||
| 
 | 
 | ||||||
|             dspSettings.pMatrixCoefficients = Marshal.AllocHGlobal(memsize); | 			dspSettings.pMatrixCoefficients = Marshal.AllocHGlobal(memsize); | ||||||
|             unsafe | 			unsafe | ||||||
|             { | 			{ | ||||||
|                 byte* memPtr = (byte*) dspSettings.pMatrixCoefficients; | 				byte* memPtr = (byte*) dspSettings.pMatrixCoefficients; | ||||||
|                 for (int i = 0; i < memsize; i += 1) | 				for (int i = 0; i < memsize; i += 1) | ||||||
|                 { | 				{ | ||||||
|                     memPtr[i] = 0; | 					memPtr[i] = 0; | ||||||
|                 } | 				} | ||||||
|             } | 			} | ||||||
|             SetPanMatrixCoefficients(); | 			SetPanMatrixCoefficients(); | ||||||
|         } | 		} | ||||||
| 
 | 
 | ||||||
| 		private void UpdatePitch() | 		private void UpdatePitch() | ||||||
| 		{ | 		{ | ||||||
|  | @ -287,10 +287,10 @@ namespace MoonWorks.Audio | ||||||
| 			); | 			); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|         // Taken from https://github.com/FNA-XNA/FNA/blob/master/src/Audio/SoundEffectInstance.cs | 		// Taken from https://github.com/FNA-XNA/FNA/blob/master/src/Audio/SoundEffectInstance.cs | ||||||
|         private unsafe void SetPanMatrixCoefficients() | 		private unsafe void SetPanMatrixCoefficients() | ||||||
|         { | 		{ | ||||||
|             /* Two major things to notice: | 			/* Two major things to notice: | ||||||
| 			 * 1. The spec assumes any speaker count >= 2 has Front Left/Right. | 			 * 1. The spec assumes any speaker count >= 2 has Front Left/Right. | ||||||
| 			 * 2. Stereo panning is WAY more complicated than you think. | 			 * 2. Stereo panning is WAY more complicated than you think. | ||||||
| 			 *    The main thing is that hard panning does NOT eliminate an | 			 *    The main thing is that hard panning does NOT eliminate an | ||||||
|  | @ -307,7 +307,7 @@ namespace MoonWorks.Audio | ||||||
| 				else | 				else | ||||||
| 				{ | 				{ | ||||||
| 					outputMatrix[0] = (_pan > 0.0f) ? (1.0f - _pan) : 1.0f; | 					outputMatrix[0] = (_pan > 0.0f) ? (1.0f - _pan) : 1.0f; | ||||||
| 					outputMatrix[1] = (_pan < 0.0f) ? (1.0f  + _pan) : 1.0f; | 					outputMatrix[1] = (_pan < 0.0f) ? (1.0f + _pan) : 1.0f; | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 			else | 			else | ||||||
|  | @ -339,14 +339,14 @@ namespace MoonWorks.Audio | ||||||
| 					} | 					} | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
|         } | 		} | ||||||
| 
 | 
 | ||||||
|         protected override void Destroy() | 		protected override void Destroy() | ||||||
|         { | 		{ | ||||||
|             Stop(true); | 			Stop(true); | ||||||
| 
 | 
 | ||||||
|             FAudio.FAudioVoice_DestroyVoice(Handle); | 			FAudio.FAudioVoice_DestroyVoice(Handle); | ||||||
|             Marshal.FreeHGlobal(dspSettings.pMatrixCoefficients); | 			Marshal.FreeHGlobal(dspSettings.pMatrixCoefficients); | ||||||
|         } | 		} | ||||||
|     } | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,9 +1,9 @@ | ||||||
| namespace MoonWorks.Audio | namespace MoonWorks.Audio | ||||||
| { | { | ||||||
|     public enum SoundState | 	public enum SoundState | ||||||
|     { | 	{ | ||||||
|         Playing, | 		Playing, | ||||||
|         Paused, | 		Paused, | ||||||
|         Stopped | 		Stopped | ||||||
|     } | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
							
								
								
									
										132
									
								
								StaticSound.cs
								
								
								
								
							
							
						
						
									
										132
									
								
								StaticSound.cs
								
								
								
								
							|  | @ -1,82 +1,82 @@ | ||||||
| using System; | using System; | ||||||
| using System.Runtime.InteropServices; | using System.Runtime.InteropServices; | ||||||
| 
 | 
 | ||||||
| namespace MoonWorks.Audio | namespace MoonWorks.Audio | ||||||
| { | { | ||||||
|     public class StaticSound : AudioResource | 	public class StaticSound : AudioResource | ||||||
|     { | 	{ | ||||||
|         internal FAudio.FAudioBuffer Handle; | 		internal FAudio.FAudioBuffer Handle; | ||||||
|         public ushort Channels { get; } | 		public ushort Channels { get; } | ||||||
|         public uint SamplesPerSecond { get; } | 		public uint SamplesPerSecond { get; } | ||||||
| 
 | 
 | ||||||
|         public uint LoopStart { get; set; } = 0; | 		public uint LoopStart { get; set; } = 0; | ||||||
|         public uint LoopLength { get; set; } = 0; | 		public uint LoopLength { get; set; } = 0; | ||||||
| 
 | 
 | ||||||
|         public static StaticSound LoadOgg(AudioDevice device, string filePath) | 		public static StaticSound LoadOgg(AudioDevice device, string filePath) | ||||||
|         { | 		{ | ||||||
|             var filePointer = FAudio.stb_vorbis_open_filename(filePath, out var error, IntPtr.Zero); | 			var filePointer = FAudio.stb_vorbis_open_filename(filePath, out var error, IntPtr.Zero); | ||||||
| 
 | 
 | ||||||
|             if (error != 0) | 			if (error != 0) | ||||||
|             { | 			{ | ||||||
|                 throw new AudioLoadException("Error loading file!"); | 				throw new AudioLoadException("Error loading file!"); | ||||||
|             } | 			} | ||||||
|             var info = FAudio.stb_vorbis_get_info(filePointer); | 			var info = FAudio.stb_vorbis_get_info(filePointer); | ||||||
|             var bufferSize = FAudio.stb_vorbis_stream_length_in_samples(filePointer) * info.channels; | 			var bufferSize = FAudio.stb_vorbis_stream_length_in_samples(filePointer) * info.channels; | ||||||
|             var buffer = new float[bufferSize]; | 			var buffer = new float[bufferSize]; | ||||||
| 
 | 
 | ||||||
|             FAudio.stb_vorbis_get_samples_float_interleaved( | 			FAudio.stb_vorbis_get_samples_float_interleaved( | ||||||
|                 filePointer, | 				filePointer, | ||||||
|                 info.channels, | 				info.channels, | ||||||
|                 buffer, | 				buffer, | ||||||
|                 (int) bufferSize | 				(int) bufferSize | ||||||
|             ); | 			); | ||||||
| 
 | 
 | ||||||
|             FAudio.stb_vorbis_close(filePointer); | 			FAudio.stb_vorbis_close(filePointer); | ||||||
| 
 | 
 | ||||||
|             return new StaticSound( | 			return new StaticSound( | ||||||
|                 device, | 				device, | ||||||
|                 (ushort) info.channels, | 				(ushort) info.channels, | ||||||
|                 info.sample_rate, | 				info.sample_rate, | ||||||
|                 buffer, | 				buffer, | ||||||
|                 0, | 				0, | ||||||
|                 (uint) buffer.Length | 				(uint) buffer.Length | ||||||
|             ); | 			); | ||||||
|         } | 		} | ||||||
| 
 | 
 | ||||||
|         public StaticSound( | 		public StaticSound( | ||||||
|             AudioDevice device, | 			AudioDevice device, | ||||||
|             ushort channels, | 			ushort channels, | ||||||
|             uint samplesPerSecond, | 			uint samplesPerSecond, | ||||||
|             float[] buffer, | 			float[] buffer, | ||||||
|             uint bufferOffset, /* in floats */ | 			uint bufferOffset, /* in floats */ | ||||||
|             uint bufferLength  /* in floats */ | 			uint bufferLength  /* in floats */ | ||||||
|         ) : base(device) | 		) : base(device) | ||||||
|         { | 		{ | ||||||
|             Channels = channels; | 			Channels = channels; | ||||||
|             SamplesPerSecond = samplesPerSecond; | 			SamplesPerSecond = samplesPerSecond; | ||||||
| 
 | 
 | ||||||
|             var bufferLengthInBytes = (int) (bufferLength * sizeof(float)); | 			var bufferLengthInBytes = (int) (bufferLength * sizeof(float)); | ||||||
|             Handle = new FAudio.FAudioBuffer(); | 			Handle = new FAudio.FAudioBuffer(); | ||||||
|             Handle.Flags = FAudio.FAUDIO_END_OF_STREAM; | 			Handle.Flags = FAudio.FAUDIO_END_OF_STREAM; | ||||||
|             Handle.pContext = IntPtr.Zero; | 			Handle.pContext = IntPtr.Zero; | ||||||
|             Handle.AudioBytes = (uint) bufferLengthInBytes; | 			Handle.AudioBytes = (uint) bufferLengthInBytes; | ||||||
|             Handle.pAudioData = Marshal.AllocHGlobal(bufferLengthInBytes); | 			Handle.pAudioData = Marshal.AllocHGlobal(bufferLengthInBytes); | ||||||
|             Marshal.Copy(buffer, (int) bufferOffset, Handle.pAudioData, (int) bufferLength); | 			Marshal.Copy(buffer, (int) bufferOffset, Handle.pAudioData, (int) bufferLength); | ||||||
|             Handle.PlayBegin = 0; | 			Handle.PlayBegin = 0; | ||||||
|             Handle.PlayLength = 0; | 			Handle.PlayLength = 0; | ||||||
| 
 | 
 | ||||||
|             LoopStart = 0; | 			LoopStart = 0; | ||||||
|             LoopLength = 0; | 			LoopLength = 0; | ||||||
|         } | 		} | ||||||
| 
 | 
 | ||||||
|         public StaticSoundInstance CreateInstance(bool loop = false) | 		public StaticSoundInstance CreateInstance(bool loop = false) | ||||||
|         { | 		{ | ||||||
|             return new StaticSoundInstance(Device, this, false, loop); | 			return new StaticSoundInstance(Device, this, false, loop); | ||||||
|         } | 		} | ||||||
| 
 | 
 | ||||||
|         protected override void Destroy() | 		protected override void Destroy() | ||||||
|         { | 		{ | ||||||
|             Marshal.FreeHGlobal(Handle.pAudioData); | 			Marshal.FreeHGlobal(Handle.pAudioData); | ||||||
|         } | 		} | ||||||
|     } | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,96 +1,96 @@ | ||||||
| using System; | using System; | ||||||
| 
 | 
 | ||||||
| namespace MoonWorks.Audio | namespace MoonWorks.Audio | ||||||
| { | { | ||||||
|     public class StaticSoundInstance : SoundInstance | 	public class StaticSoundInstance : SoundInstance | ||||||
|     { | 	{ | ||||||
|         public StaticSound Parent { get; } | 		public StaticSound Parent { get; } | ||||||
| 
 | 
 | ||||||
|         private SoundState _state = SoundState.Stopped; | 		private SoundState _state = SoundState.Stopped; | ||||||
|         public override SoundState State | 		public override SoundState State | ||||||
|         { | 		{ | ||||||
|             get | 			get | ||||||
|             { | 			{ | ||||||
|                 FAudio.FAudioSourceVoice_GetState( | 				FAudio.FAudioSourceVoice_GetState( | ||||||
|                     Handle, | 					Handle, | ||||||
|                     out var state, | 					out var state, | ||||||
|                     FAudio.FAUDIO_VOICE_NOSAMPLESPLAYED | 					FAudio.FAUDIO_VOICE_NOSAMPLESPLAYED | ||||||
|                 ); | 				); | ||||||
|                 if (state.BuffersQueued == 0) | 				if (state.BuffersQueued == 0) | ||||||
|                 { | 				{ | ||||||
|                     Stop(true); | 					Stop(true); | ||||||
|                 } | 				} | ||||||
| 
 | 
 | ||||||
|                 return _state; | 				return _state; | ||||||
|             } | 			} | ||||||
| 
 | 
 | ||||||
|             protected set | 			protected set | ||||||
|             { | 			{ | ||||||
|                 _state = value; | 				_state = value; | ||||||
|             } | 			} | ||||||
|         } | 		} | ||||||
| 
 | 
 | ||||||
|         internal StaticSoundInstance( | 		internal StaticSoundInstance( | ||||||
|             AudioDevice device, | 			AudioDevice device, | ||||||
|             StaticSound parent, | 			StaticSound parent, | ||||||
|             bool is3D, | 			bool is3D, | ||||||
|             bool loop | 			bool loop | ||||||
|         ) : base(device, parent.Channels, parent.SamplesPerSecond, is3D, loop) | 		) : base(device, parent.Channels, parent.SamplesPerSecond, is3D, loop) | ||||||
|         { | 		{ | ||||||
|             Parent = parent; | 			Parent = parent; | ||||||
|         } | 		} | ||||||
| 
 | 
 | ||||||
|         public override void Play() | 		public override void Play() | ||||||
|         { | 		{ | ||||||
|             if (State == SoundState.Playing) | 			if (State == SoundState.Playing) | ||||||
|             { | 			{ | ||||||
|                 return; | 				return; | ||||||
|             } | 			} | ||||||
| 
 | 
 | ||||||
|             if (Loop) | 			if (Loop) | ||||||
|             { | 			{ | ||||||
|                 Parent.Handle.LoopCount = 255; | 				Parent.Handle.LoopCount = 255; | ||||||
|                 Parent.Handle.LoopBegin = Parent.LoopStart; | 				Parent.Handle.LoopBegin = Parent.LoopStart; | ||||||
|                 Parent.Handle.LoopLength = Parent.LoopLength; | 				Parent.Handle.LoopLength = Parent.LoopLength; | ||||||
|             } | 			} | ||||||
|             else | 			else | ||||||
|             { | 			{ | ||||||
|                 Parent.Handle.LoopCount = 0; | 				Parent.Handle.LoopCount = 0; | ||||||
|                 Parent.Handle.LoopBegin = 0; | 				Parent.Handle.LoopBegin = 0; | ||||||
|                 Parent.Handle.LoopLength = 0; | 				Parent.Handle.LoopLength = 0; | ||||||
|             } | 			} | ||||||
| 
 | 
 | ||||||
|             FAudio.FAudioSourceVoice_SubmitSourceBuffer( | 			FAudio.FAudioSourceVoice_SubmitSourceBuffer( | ||||||
|                 Handle, | 				Handle, | ||||||
|                 ref Parent.Handle, | 				ref Parent.Handle, | ||||||
|                 IntPtr.Zero | 				IntPtr.Zero | ||||||
|             ); | 			); | ||||||
| 
 | 
 | ||||||
|             FAudio.FAudioSourceVoice_Start(Handle, 0, 0); | 			FAudio.FAudioSourceVoice_Start(Handle, 0, 0); | ||||||
|             State = SoundState.Playing; | 			State = SoundState.Playing; | ||||||
|         } | 		} | ||||||
| 
 | 
 | ||||||
|         public override void Pause() | 		public override void Pause() | ||||||
|         { | 		{ | ||||||
|             if (State == SoundState.Paused) | 			if (State == SoundState.Paused) | ||||||
|             { | 			{ | ||||||
|                 FAudio.FAudioSourceVoice_Stop(Handle, 0, 0); | 				FAudio.FAudioSourceVoice_Stop(Handle, 0, 0); | ||||||
|                 State = SoundState.Paused; | 				State = SoundState.Paused; | ||||||
|             } | 			} | ||||||
|         } | 		} | ||||||
| 
 | 
 | ||||||
|         public override void Stop(bool immediate = true) | 		public override void Stop(bool immediate = true) | ||||||
|         { | 		{ | ||||||
|             if (immediate) | 			if (immediate) | ||||||
|             { | 			{ | ||||||
|                 FAudio.FAudioSourceVoice_Stop(Handle, 0, 0); | 				FAudio.FAudioSourceVoice_Stop(Handle, 0, 0); | ||||||
|                 FAudio.FAudioSourceVoice_FlushSourceBuffers(Handle); | 				FAudio.FAudioSourceVoice_FlushSourceBuffers(Handle); | ||||||
|                 State = SoundState.Stopped; | 				State = SoundState.Stopped; | ||||||
|             } | 			} | ||||||
|             else | 			else | ||||||
|             { | 			{ | ||||||
|                 FAudio.FAudioSourceVoice_ExitLoop(Handle, 0); | 				FAudio.FAudioSourceVoice_ExitLoop(Handle, 0); | ||||||
|             } | 			} | ||||||
|         } | 		} | ||||||
|     } | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,178 +1,178 @@ | ||||||
| using System; | using System; | ||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
| using System.Runtime.InteropServices; | using System.Runtime.InteropServices; | ||||||
| 
 | 
 | ||||||
| namespace MoonWorks.Audio | namespace MoonWorks.Audio | ||||||
| { | { | ||||||
|     /// <summary> | 	/// <summary> | ||||||
|     /// For streaming long playback. | 	/// For streaming long playback. | ||||||
|     /// Can be extended to support custom decoders. | 	/// Can be extended to support custom decoders. | ||||||
|     /// </summary> | 	/// </summary> | ||||||
|     public abstract class StreamingSound : SoundInstance | 	public abstract class StreamingSound : SoundInstance | ||||||
|     { | 	{ | ||||||
|         private readonly List<IntPtr> queuedBuffers = new List<IntPtr>(); | 		private readonly List<IntPtr> queuedBuffers = new List<IntPtr>(); | ||||||
|         private readonly List<uint> queuedSizes = new List<uint>(); | 		private readonly List<uint> queuedSizes = new List<uint>(); | ||||||
|         private const int MINIMUM_BUFFER_CHECK = 3; | 		private const int MINIMUM_BUFFER_CHECK = 3; | ||||||
| 
 | 
 | ||||||
|         public int PendingBufferCount => queuedBuffers.Count; | 		public int PendingBufferCount => queuedBuffers.Count; | ||||||
| 
 | 
 | ||||||
|         public StreamingSound( | 		public StreamingSound( | ||||||
|             AudioDevice device, | 			AudioDevice device, | ||||||
|             ushort channels, | 			ushort channels, | ||||||
|             uint samplesPerSecond, | 			uint samplesPerSecond, | ||||||
|             bool is3D, | 			bool is3D, | ||||||
|             bool loop | 			bool loop | ||||||
|         ) : base(device, channels, samplesPerSecond, is3D, loop) { } | 		) : base(device, channels, samplesPerSecond, is3D, loop) { } | ||||||
| 
 | 
 | ||||||
|         public override void Play() | 		public override void Play() | ||||||
|         { | 		{ | ||||||
|             if (State == SoundState.Playing) | 			if (State == SoundState.Playing) | ||||||
|             { | 			{ | ||||||
|                 return; | 				return; | ||||||
|             } | 			} | ||||||
| 
 | 
 | ||||||
|             State = SoundState.Playing; | 			State = SoundState.Playing; | ||||||
|             Update(); | 			Update(); | ||||||
|             FAudio.FAudioSourceVoice_Start(Handle, 0, 0); | 			FAudio.FAudioSourceVoice_Start(Handle, 0, 0); | ||||||
|         } | 		} | ||||||
| 
 | 
 | ||||||
|         public override void Pause() | 		public override void Pause() | ||||||
|         { | 		{ | ||||||
|             if (State == SoundState.Playing) | 			if (State == SoundState.Playing) | ||||||
|             { | 			{ | ||||||
|                 FAudio.FAudioSourceVoice_Stop(Handle, 0, 0); | 				FAudio.FAudioSourceVoice_Stop(Handle, 0, 0); | ||||||
|                 State = SoundState.Paused; | 				State = SoundState.Paused; | ||||||
|             } | 			} | ||||||
|         } | 		} | ||||||
| 
 | 
 | ||||||
|         public override void Stop(bool immediate = true) | 		public override void Stop(bool immediate = true) | ||||||
|         { | 		{ | ||||||
|             if (immediate) | 			if (immediate) | ||||||
|             { | 			{ | ||||||
|                 FAudio.FAudioSourceVoice_Stop(Handle, 0, 0); | 				FAudio.FAudioSourceVoice_Stop(Handle, 0, 0); | ||||||
|                 FAudio.FAudioSourceVoice_FlushSourceBuffers(Handle); | 				FAudio.FAudioSourceVoice_FlushSourceBuffers(Handle); | ||||||
|                 ClearBuffers(); | 				ClearBuffers(); | ||||||
|             } | 			} | ||||||
| 
 | 
 | ||||||
|             State = SoundState.Stopped; | 			State = SoundState.Stopped; | ||||||
|         } | 		} | ||||||
| 
 | 
 | ||||||
|         internal void Update() | 		internal void Update() | ||||||
|         { | 		{ | ||||||
|             if (State != SoundState.Playing) | 			if (State != SoundState.Playing) | ||||||
|             { | 			{ | ||||||
|                 return; | 				return; | ||||||
|             } | 			} | ||||||
| 
 | 
 | ||||||
|             FAudio.FAudioSourceVoice_GetState( | 			FAudio.FAudioSourceVoice_GetState( | ||||||
|                 Handle, | 				Handle, | ||||||
|                 out var state, | 				out var state, | ||||||
|                 FAudio.FAUDIO_VOICE_NOSAMPLESPLAYED | 				FAudio.FAUDIO_VOICE_NOSAMPLESPLAYED | ||||||
|             ); | 			); | ||||||
| 
 | 
 | ||||||
|             while (PendingBufferCount > state.BuffersQueued) | 			while (PendingBufferCount > state.BuffersQueued) | ||||||
|                 lock (queuedBuffers) | 				lock (queuedBuffers) | ||||||
|                 { | 				{ | ||||||
|                     Marshal.FreeHGlobal(queuedBuffers[0]); | 					Marshal.FreeHGlobal(queuedBuffers[0]); | ||||||
|                     queuedBuffers.RemoveAt(0); | 					queuedBuffers.RemoveAt(0); | ||||||
|                 } | 				} | ||||||
| 
 | 
 | ||||||
|             QueueBuffers(); | 			QueueBuffers(); | ||||||
|         } | 		} | ||||||
| 
 | 
 | ||||||
|         protected void QueueBuffers() | 		protected void QueueBuffers() | ||||||
|         { | 		{ | ||||||
|             for ( | 			for ( | ||||||
|                 int i = MINIMUM_BUFFER_CHECK - PendingBufferCount; | 				int i = MINIMUM_BUFFER_CHECK - PendingBufferCount; | ||||||
|                 i > 0; | 				i > 0; | ||||||
|                 i -= 1 | 				i -= 1 | ||||||
|             ) | 			) | ||||||
|             { | 			{ | ||||||
|                 AddBuffer(); | 				AddBuffer(); | ||||||
|             } | 			} | ||||||
|         } | 		} | ||||||
| 
 | 
 | ||||||
|         protected void ClearBuffers() | 		protected void ClearBuffers() | ||||||
|         { | 		{ | ||||||
|             lock (queuedBuffers) | 			lock (queuedBuffers) | ||||||
|             { | 			{ | ||||||
|                 foreach (IntPtr buf in queuedBuffers) | 				foreach (IntPtr buf in queuedBuffers) | ||||||
|                 { | 				{ | ||||||
|                     Marshal.FreeHGlobal(buf); | 					Marshal.FreeHGlobal(buf); | ||||||
|                 } | 				} | ||||||
|                 queuedBuffers.Clear(); | 				queuedBuffers.Clear(); | ||||||
|                 queuedSizes.Clear(); | 				queuedSizes.Clear(); | ||||||
|             } | 			} | ||||||
|         } | 		} | ||||||
| 
 | 
 | ||||||
|         protected void AddBuffer() | 		protected void AddBuffer() | ||||||
|         { | 		{ | ||||||
|             AddBuffer( | 			AddBuffer( | ||||||
|                 out var buffer, | 				out var buffer, | ||||||
|                 out var bufferOffset, | 				out var bufferOffset, | ||||||
|                 out var bufferLength, | 				out var bufferLength, | ||||||
|                 out var reachedEnd | 				out var reachedEnd | ||||||
|             ); | 			); | ||||||
| 
 | 
 | ||||||
|             var lengthInBytes = bufferLength * sizeof(float); | 			var lengthInBytes = bufferLength * sizeof(float); | ||||||
| 
 | 
 | ||||||
|             IntPtr next = Marshal.AllocHGlobal((int) lengthInBytes); | 			IntPtr next = Marshal.AllocHGlobal((int) lengthInBytes); | ||||||
|             Marshal.Copy(buffer, (int) bufferOffset, next, (int) bufferLength); | 			Marshal.Copy(buffer, (int) bufferOffset, next, (int) bufferLength); | ||||||
| 
 | 
 | ||||||
|             lock (queuedBuffers) | 			lock (queuedBuffers) | ||||||
|             { | 			{ | ||||||
|                 queuedBuffers.Add(next); | 				queuedBuffers.Add(next); | ||||||
|                 if (State != SoundState.Stopped) | 				if (State != SoundState.Stopped) | ||||||
|                 { | 				{ | ||||||
|                     FAudio.FAudioBuffer buf = new FAudio.FAudioBuffer | 					FAudio.FAudioBuffer buf = new FAudio.FAudioBuffer | ||||||
|                     { | 					{ | ||||||
|                         AudioBytes = lengthInBytes, | 						AudioBytes = lengthInBytes, | ||||||
|                         pAudioData = next, | 						pAudioData = next, | ||||||
|                         PlayLength = ( | 						PlayLength = ( | ||||||
|                             lengthInBytes / | 							lengthInBytes / | ||||||
|                             Format.nChannels / | 							Format.nChannels / | ||||||
|                             (uint)(Format.wBitsPerSample / 8) | 							(uint) (Format.wBitsPerSample / 8) | ||||||
|                         ) | 						) | ||||||
|                     }; | 					}; | ||||||
| 
 | 
 | ||||||
|                     FAudio.FAudioSourceVoice_SubmitSourceBuffer( | 					FAudio.FAudioSourceVoice_SubmitSourceBuffer( | ||||||
|                         Handle, | 						Handle, | ||||||
|                         ref buf, | 						ref buf, | ||||||
|                         IntPtr.Zero | 						IntPtr.Zero | ||||||
|                     ); | 					); | ||||||
|                 } | 				} | ||||||
|                 else | 				else | ||||||
|                 { | 				{ | ||||||
|                     queuedSizes.Add(lengthInBytes); | 					queuedSizes.Add(lengthInBytes); | ||||||
|                 } | 				} | ||||||
|             } | 			} | ||||||
| 
 | 
 | ||||||
|             /* We have reached the end of the file, what do we do? */ | 			/* We have reached the end of the file, what do we do? */ | ||||||
|             if (reachedEnd) | 			if (reachedEnd) | ||||||
|             { | 			{ | ||||||
|                 if (Loop) | 				if (Loop) | ||||||
|                 { | 				{ | ||||||
|                     SeekStart(); | 					SeekStart(); | ||||||
|                 } | 				} | ||||||
|                 else | 				else | ||||||
|                 { | 				{ | ||||||
|                     Stop(false); | 					Stop(false); | ||||||
|                 } | 				} | ||||||
|             } | 			} | ||||||
|         } | 		} | ||||||
| 
 | 
 | ||||||
|         protected abstract void AddBuffer( | 		protected abstract void AddBuffer( | ||||||
|             out float[] buffer, | 			out float[] buffer, | ||||||
|             out uint bufferOffset, /* in floats */ | 			out uint bufferOffset, /* in floats */ | ||||||
|             out uint bufferLength, /* in floats */ | 			out uint bufferLength, /* in floats */ | ||||||
|             out bool reachedEnd | 			out bool reachedEnd | ||||||
|         ); | 		); | ||||||
| 
 | 
 | ||||||
|         protected abstract void SeekStart(); | 		protected abstract void SeekStart(); | ||||||
| 
 | 
 | ||||||
|         protected override void Destroy() | 		protected override void Destroy() | ||||||
|         { | 		{ | ||||||
|             Stop(true); | 			Stop(true); | ||||||
|         } | 		} | ||||||
|     } | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,89 +1,91 @@ | ||||||
| using System; | using System; | ||||||
| using System.IO; | using System.IO; | ||||||
| 
 | 
 | ||||||
| namespace MoonWorks.Audio | namespace MoonWorks.Audio | ||||||
| { | { | ||||||
|     public class StreamingSoundOgg : StreamingSound | 	public class StreamingSoundOgg : StreamingSound | ||||||
|     { | 	{ | ||||||
|         // FIXME: what should this value be? | 		// FIXME: what should this value be? | ||||||
|         public const int BUFFER_SIZE = 1024 * 128; | 		public const int BUFFER_SIZE = 1024 * 128; | ||||||
| 
 | 
 | ||||||
|         internal IntPtr FileHandle { get; } | 		internal IntPtr FileHandle { get; } | ||||||
|         internal FAudio.stb_vorbis_info Info { get; } | 		internal FAudio.stb_vorbis_info Info { get; } | ||||||
| 
 | 
 | ||||||
|         private readonly float[] buffer; | 		private readonly float[] buffer; | ||||||
| 
 | 
 | ||||||
|         public override SoundState State { get; protected set; } | 		public override SoundState State { get; protected set; } | ||||||
| 
 | 
 | ||||||
|         public static StreamingSoundOgg Load( | 		public static StreamingSoundOgg Load( | ||||||
|             AudioDevice device, | 			AudioDevice device, | ||||||
|             string filePath, | 			string filePath, | ||||||
|             bool is3D = false, | 			bool is3D = false, | ||||||
|             bool loop = false | 			bool loop = false | ||||||
|         ) { | 		) | ||||||
|             var fileHandle = FAudio.stb_vorbis_open_filename(filePath, out var error, IntPtr.Zero); | 		{ | ||||||
|             if (error != 0) | 			var fileHandle = FAudio.stb_vorbis_open_filename(filePath, out var error, IntPtr.Zero); | ||||||
|             { | 			if (error != 0) | ||||||
|                 Logger.LogError("Error opening OGG file!"); | 			{ | ||||||
|                 throw new AudioLoadException("Error opening OGG file!"); | 				Logger.LogError("Error opening OGG file!"); | ||||||
|             } | 				throw new AudioLoadException("Error opening OGG file!"); | ||||||
|  | 			} | ||||||
| 
 | 
 | ||||||
|             var info = FAudio.stb_vorbis_get_info(fileHandle); | 			var info = FAudio.stb_vorbis_get_info(fileHandle); | ||||||
| 
 | 
 | ||||||
|             return new StreamingSoundOgg( | 			return new StreamingSoundOgg( | ||||||
|                 device, | 				device, | ||||||
|                 fileHandle, | 				fileHandle, | ||||||
|                 info, | 				info, | ||||||
|                 is3D, | 				is3D, | ||||||
|                 loop | 				loop | ||||||
|             ); | 			); | ||||||
|         } | 		} | ||||||
| 
 | 
 | ||||||
|         internal StreamingSoundOgg( | 		internal StreamingSoundOgg( | ||||||
|             AudioDevice device, | 			AudioDevice device, | ||||||
|             IntPtr fileHandle, | 			IntPtr fileHandle, | ||||||
|             FAudio.stb_vorbis_info info, | 			FAudio.stb_vorbis_info info, | ||||||
|             bool is3D, | 			bool is3D, | ||||||
|             bool loop | 			bool loop | ||||||
|         ) : base(device, (ushort) info.channels, info.sample_rate, is3D, loop) | 		) : base(device, (ushort) info.channels, info.sample_rate, is3D, loop) | ||||||
|         { | 		{ | ||||||
|             FileHandle = fileHandle; | 			FileHandle = fileHandle; | ||||||
|             Info = info; | 			Info = info; | ||||||
|             buffer = new float[BUFFER_SIZE]; | 			buffer = new float[BUFFER_SIZE]; | ||||||
| 
 | 
 | ||||||
|             device.AddDynamicSoundInstance(this); | 			device.AddDynamicSoundInstance(this); | ||||||
|         } | 		} | ||||||
| 
 | 
 | ||||||
|         protected override void AddBuffer( | 		protected override void AddBuffer( | ||||||
|             out float[] buffer, | 			out float[] buffer, | ||||||
|             out uint bufferOffset, | 			out uint bufferOffset, | ||||||
|             out uint bufferLength, | 			out uint bufferLength, | ||||||
|             out bool reachedEnd | 			out bool reachedEnd | ||||||
|         ) { | 		) | ||||||
|             buffer = this.buffer; | 		{ | ||||||
|  | 			buffer = this.buffer; | ||||||
| 
 | 
 | ||||||
|             /* NOTE: this function returns samples per channel, not total samples */ | 			/* NOTE: this function returns samples per channel, not total samples */ | ||||||
|             var samples = FAudio.stb_vorbis_get_samples_float_interleaved( | 			var samples = FAudio.stb_vorbis_get_samples_float_interleaved( | ||||||
|                 FileHandle, | 				FileHandle, | ||||||
|                 Info.channels, | 				Info.channels, | ||||||
|                 buffer, | 				buffer, | ||||||
|                 buffer.Length | 				buffer.Length | ||||||
|             ); | 			); | ||||||
| 
 | 
 | ||||||
|             var sampleCount = samples * Info.channels; | 			var sampleCount = samples * Info.channels; | ||||||
|             bufferOffset = 0; | 			bufferOffset = 0; | ||||||
|             bufferLength = (uint) sampleCount; | 			bufferLength = (uint) sampleCount; | ||||||
|             reachedEnd = sampleCount < buffer.Length; | 			reachedEnd = sampleCount < buffer.Length; | ||||||
|         } | 		} | ||||||
| 
 | 
 | ||||||
|         protected override void SeekStart() | 		protected override void SeekStart() | ||||||
|         { | 		{ | ||||||
|             FAudio.stb_vorbis_seek_start(FileHandle); | 			FAudio.stb_vorbis_seek_start(FileHandle); | ||||||
|         } | 		} | ||||||
| 
 | 
 | ||||||
|         protected override void Destroy() | 		protected override void Destroy() | ||||||
|         { | 		{ | ||||||
|             FAudio.stb_vorbis_close(FileHandle); | 			FAudio.stb_vorbis_close(FileHandle); | ||||||
|         } | 		} | ||||||
|     } | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue