using System; using System.Runtime.InteropServices; using SharpDX.Multimedia; namespace SharpDX.XAPO { /// /// Internal AudioProcessorShadow /// /// IXAPO GUID [Guid("a90bc001-e897-e897-55e4-9e4700000000")] internal class AudioProcessorShadow : ComObjectShadow { private static readonly AudioProcessorVtbl Vtbl = new AudioProcessorVtbl(); /// /// Return a pointer to the unmanaged version of this callback. /// /// The callback. /// A pointer to a shadow c++ callback public static IntPtr ToIntPtr(AudioProcessor callback) { return ToCallbackPtr(callback); } public class AudioProcessorVtbl : ComObjectVtbl { public AudioProcessorVtbl() : base(10) { unsafe { AddMethod(new GetRegistrationPropertiesDelegate(GetRegistrationPropertiesImpl)); AddMethod(new IsInputFormatSupportedDelegate(IsInputFormatSupportedImpl)); AddMethod(new IsOutputFormatSupportedDelegate(IsOutputFormatSupportedImpl)); AddMethod(new InitializeDelegate(InitializeImpl)); AddMethod(new ResetDelegate(ResetImpl)); AddMethod(new LockForProcessDelegate(LockForProcessImpl)); AddMethod(new UnlockForProcessDelegate(UnlockForProcessImpl)); AddMethod(new ProcessDelegate(ProcessImpl)); AddMethod(new CalcInputFramesDelegate(CalcInputFramesImpl)); AddMethod(new CalcOutputFramesDelegate(CalcOutputFramesImpl)); } } /// HRESULT IXAPO::GetRegistrationProperties([Out] XAPO_REGISTRATION_PROPERTIES** ppRegistrationProperties) [UnmanagedFunctionPointer(CallingConvention.StdCall)] private delegate int GetRegistrationPropertiesDelegate(IntPtr thisObject, out IntPtr output); private static int GetRegistrationPropertiesImpl(IntPtr thisObject, out IntPtr output) { output = IntPtr.Zero; try { var shadow = ToShadow(thisObject); var callback = (AudioProcessor)shadow.Callback; int sizeOfNative = Utilities.SizeOf(); output = Marshal.AllocCoTaskMem(sizeOfNative); RegistrationProperties.__Native temp = default(RegistrationProperties.__Native); callback.RegistrationProperties.__MarshalTo(ref temp); Utilities.Write(output, ref temp); } catch (Exception exception) { return (int)SharpDX.Result.GetResultFromException(exception); } return Result.Ok.Code; } /// HRESULT IXAPO::IsInputFormatSupported([None] const WAVEFORMATEX* pOutputFormat,[None] const WAVEFORMATEX* pRequestedInputFormat,[Out, Optional] WAVEFORMATEX** ppSupportedInputFormat) [UnmanagedFunctionPointer(CallingConvention.StdCall)] private delegate int IsInputFormatSupportedDelegate(IntPtr thisObject, IntPtr outputFormat, IntPtr requestedInputFormat, out IntPtr supportedInputFormat); private static int IsInputFormatSupportedImpl(IntPtr thisObject, IntPtr pOutputFormat, IntPtr pRequestedInputFormat, out IntPtr pSupportedInputFormat) { pSupportedInputFormat = IntPtr.Zero; try { var shadow = ToShadow(thisObject); var callback = (AudioProcessor)shadow.Callback; WaveFormat outputFormat = WaveFormat.MarshalFrom(pOutputFormat); WaveFormat requestedInputFormat = WaveFormat.MarshalFrom(pRequestedInputFormat); WaveFormat supportedInputFormat; var result = callback.IsInputFormatSupported(outputFormat, requestedInputFormat, out supportedInputFormat); int sizeOfWaveFormat = Marshal.SizeOf(supportedInputFormat); pSupportedInputFormat = Marshal.AllocCoTaskMem(sizeOfWaveFormat); Marshal.StructureToPtr(supportedInputFormat, pSupportedInputFormat, false); // return XAPO_E_FORMAT_UNSUPPORTED if fail return result ? Result.Ok.Code : unchecked((int)0x88970001); } catch (Exception exception) { return (int)SharpDX.Result.GetResultFromException(exception); } } /// HRESULT IXAPO::IsOutputFormatSupported([None] const WAVEFORMATEX* pInputFormat,[None] const WAVEFORMATEX* pRequestedOutputFormat,[Out, Optional] WAVEFORMATEX** ppSupportedOutputFormat) [UnmanagedFunctionPointer(CallingConvention.StdCall)] private delegate int IsOutputFormatSupportedDelegate(IntPtr thisObject, IntPtr outputFormat, IntPtr requestedInputFormat, out IntPtr supportedInputFormat); private static int IsOutputFormatSupportedImpl(IntPtr thisObject, IntPtr pInputFormat, IntPtr pRequestedOutputFormat, out IntPtr pSupportedOutputFormat) { pSupportedOutputFormat = IntPtr.Zero; try { var shadow = ToShadow(thisObject); var callback = (AudioProcessor)shadow.Callback; WaveFormat inputFormat = WaveFormat.MarshalFrom(pInputFormat); WaveFormat requestedOutputFormat = WaveFormat.MarshalFrom(pRequestedOutputFormat); WaveFormat supportedOutputFormat; var result = callback.IsOutputFormatSupported(inputFormat, requestedOutputFormat, out supportedOutputFormat); int sizeOfWaveFormat = Marshal.SizeOf(supportedOutputFormat); pSupportedOutputFormat = Marshal.AllocCoTaskMem(sizeOfWaveFormat); Marshal.StructureToPtr(supportedOutputFormat, pSupportedOutputFormat, false); // return XAPO_E_FORMAT_UNSUPPORTED if fail return result ? Result.Ok.Code : unchecked((int)0x88970001); } catch (Exception exception) { return (int)SharpDX.Result.GetResultFromException(exception); } } /// HRESULT IXAPO::Initialize([In, Buffer, Optional] const void* pData,[None] UINT32 DataByteSize) [UnmanagedFunctionPointer(CallingConvention.StdCall)] private delegate int InitializeDelegate(IntPtr thisObject, IntPtr ptr, int dataSize); private static int InitializeImpl(IntPtr thisObject, IntPtr ptr, int dataSize) { try { var shadow = ToShadow(thisObject); var callback = (AudioProcessor)shadow.Callback; callback.Initialize(new DataStream(ptr, dataSize, true, true)); } catch (Exception exception) { return (int)SharpDX.Result.GetResultFromException(exception); } return Result.Ok.Code; } /// void IXAPO::Reset() [UnmanagedFunctionPointer(CallingConvention.StdCall)] private delegate void ResetDelegate(IntPtr thisObject); private static void ResetImpl(IntPtr thisObject) { var shadow = ToShadow(thisObject); var callback = (AudioProcessor)shadow.Callback; callback.Reset(); } /// HRESULT IXAPO::LockForProcess([None] UINT32 InputLockedParameterCount,[In, Buffer, Optional] const XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS* pInputLockedParameters,[None] UINT32 OutputLockedParameterCount,[In, Buffer, Optional] const XAPO_LOCKFORPROCESS_BUFFER_PARAMETERS* pOutputLockedParameters) //void LockForProcess(SharpDX.XAPO.LockforprocessParameters[] inputLockedParameters, SharpDX.XAPO.LockforprocessParameters[] outputLockedParameters); [UnmanagedFunctionPointer(CallingConvention.StdCall)] private unsafe delegate int LockForProcessDelegate(IntPtr thisObject, int inputLockedParameterCount, LockParameters.__Native* pInputLockedParameters, int outputLockedParameterCount, LockParameters.__Native* pOutputLockedParameters); private static unsafe int LockForProcessImpl(IntPtr thisObject, int inputLockedParameterCount, LockParameters.__Native* pInputLockedParameters, int outputLockedParameterCount, LockParameters.__Native* pOutputLockedParameters) { try { var shadow = ToShadow(thisObject); var callback = (AudioProcessor)shadow.Callback; var inputLockedParameters = new LockParameters[inputLockedParameterCount]; for (int i = 0; i < inputLockedParameters.Length; i++) { var param = new LockParameters(); param.__MarshalFrom(&pInputLockedParameters[i]); inputLockedParameters[i] = param; } var ouputLockedParameters = new LockParameters[outputLockedParameterCount]; for (int i = 0; i < ouputLockedParameters.Length; i++) { var param = new LockParameters(); param.__MarshalFrom(&pOutputLockedParameters[i]); ouputLockedParameters[i] = param; } callback.LockForProcess(inputLockedParameters, ouputLockedParameters); } catch (Exception exception) { return (int)SharpDX.Result.GetResultFromException(exception); } return 0; } /// /// Deallocates variables that were allocated with the {{LockForProcess}} method. /// /// void IXAPO::UnlockForProcess() [UnmanagedFunctionPointer(CallingConvention.StdCall)] private delegate void UnlockForProcessDelegate(IntPtr thisObject); private static void UnlockForProcessImpl(IntPtr thisObject) { var shadow = ToShadow(thisObject); var callback = (AudioProcessor)shadow.Callback; callback.UnlockForProcess(); } /// void IXAPO::Process([None] UINT32 InputProcessParameterCount,[In, Buffer, Optional] const XAPO_PROCESS_BUFFER_PARAMETERS* pInputProcessParameters,[None] UINT32 OutputProcessParameterCount,[InOut, Buffer, Optional] XAPO_PROCESS_BUFFER_PARAMETERS* pOutputProcessParameters,[None] BOOL IsEnabled) [UnmanagedFunctionPointer(CallingConvention.StdCall)] private unsafe delegate void ProcessDelegate(IntPtr thisObject, int inputProcessParameterCount, BufferParameters* pInputProcessParameters, int outputProcessParameterCount, BufferParameters* inputProcessParameters, int isEnabled); private static unsafe void ProcessImpl(IntPtr thisObject, int inputProcessParameterCount, BufferParameters* pInputProcessParameters, int outputProcessParameterCount, BufferParameters* pOutputProcessParameters, int isEnabled) { var shadow = ToShadow(thisObject); var callback = (AudioProcessor)shadow.Callback; var inputProcessParameters = new BufferParameters[inputProcessParameterCount]; for (int i = 0; i < inputProcessParameters.Length; i++) inputProcessParameters[i] = pInputProcessParameters[i]; var outputProcessParameters = new BufferParameters[outputProcessParameterCount]; for (int i = 0; i < outputProcessParameters.Length; i++) outputProcessParameters[i] = pOutputProcessParameters[i]; //// NOTE: because XAudio currently support only 1 input and 1 output buffer at a time, don't waste our time //BufferParameters outputParameter = *pOutputProcessParameters; callback.Process(inputProcessParameters, outputProcessParameters, isEnabled == 1); //Update BufferParameters output (see doc for IXAPO::Process //ValidFrameCount must be fill by the Process method. Most of the time ValidFrameCount in input == ValidFrameCount in output (effectively written) for (int i = 0; i < outputProcessParameters.Length; i++) pOutputProcessParameters[i].ValidFrameCount = outputProcessParameters[i].ValidFrameCount; } /// /// Returns the number of input frames required to generate the given number of output frames. /// /// This pointer /// The number of output frames desired. /// No documentation. /// UINT32 IXAPO::CalcInputFrames([None] UINT32 OutputFrameCount) [UnmanagedFunctionPointer(CallingConvention.StdCall)] private delegate int CalcInputFramesDelegate(IntPtr thisObject, int outputFrameCount); private static int CalcInputFramesImpl(IntPtr thisObject, int outputFrameCount) { var shadow = ToShadow(thisObject); var callback = (AudioProcessor)shadow.Callback; return callback.CalcInputFrames(outputFrameCount); } /// /// Returns the number of output frames that will be generated from a given number of input frames. /// /// This Pointer /// The number of input frames. /// No documentation. /// UINT32 IXAPO::CalcOutputFrames([None] UINT32 InputFrameCount) [UnmanagedFunctionPointer(CallingConvention.StdCall)] private delegate int CalcOutputFramesDelegate(IntPtr thisObject, int inputFrameCount); private static int CalcOutputFramesImpl(IntPtr thisObject, int inputFrameCount) { var shadow = ToShadow(thisObject); var callback = (AudioProcessor) shadow.Callback; return callback.CalcOutputFrames(inputFrameCount); } } protected override CppObjectVtbl GetVtbl { get { return Vtbl; } } } }