/// <summary> /// Creates and configures a mastering voice. /// </summary> /// <param name="pMasteringVoice">If successful, returns a pointer to the new <see cref="XAudio2MasteringVoice" /> object.</param> /// <param name="inputChannels"> /// Number of channels the mastering voice expects in its input audio. <paramref name="inputChannels" /> must be less than /// or equal to <see cref="MaxAudioChannels" />. /// You can set InputChannels to <see cref="DefaultChannels" />, which causes XAudio2 to try to detect the system /// speaker configuration setup. /// </param> /// <param name="inputSampleRate"> /// Sample rate of the input audio data of the mastering voice. This rate must be a multiple of /// <see cref="QuantumDenominator" />. <paramref name="inputSampleRate" /> must be between <see cref="MinimumSampleRate" /> /// and <see cref="MaximumSampleRate" />. /// You can set InputSampleRate to <see cref="DefaultSampleRate" />, with the default being determined by the current /// platform. /// </param> /// <param name="flags">Flags that specify the behavior of the mastering voice. Must be 0.</param> /// <param name="deviceId"> /// Identifier of the device to receive the output audio. Specifying the default value of 0 (zero) /// causes XAudio2 to select the global default audio device. /// </param> /// <param name="effectChain"> /// <see cref="EffectChain" /> structure that describes an effect chain to use in the mastering /// voice, or NULL to use no effects. /// </param> /// <param name="streamCategory"><b>Not valid for XAudio 2.7.</b></param> /// <returns>HRESULT</returns> public override unsafe int CreateMasteringVoiceNative(out IntPtr pMasteringVoice, int inputChannels, int inputSampleRate, int flags, object deviceId, EffectChain?effectChain, AudioStreamCategory streamCategory) { if (!(deviceId is int)) { throw new ArgumentException("DeviceId has to be an integer.", "deviceId"); } var device = (int)deviceId; EffectChain value1 = effectChain.HasValue ? effectChain.Value : new EffectChain(); fixed(void *ptr = &pMasteringVoice) { return(InteropCalls.CallI( UnsafeBasePtr, ptr, inputChannels, inputSampleRate, flags, device, effectChain.HasValue ? &value1 : (void *)IntPtr.Zero, //streamCategory, ((void **)(*(void **)UnsafeBasePtr))[10])); } }
/// <summary> /// Creates and configures a source voice. For more information see /// http://msdn.microsoft.com/en-us/library/windows/desktop/microsoft.directx_sdk.ixaudio2.ixaudio2.createsourcevoice(v=vs.85).aspx. /// </summary> /// <param name="pSourceVoice">If successful, returns a pointer to the new <see cref="XAudio2SourceVoice" /> object.</param> /// <param name="sourceFormat"> /// Pointer to a <see cref="WaveFormat" />. The following formats are supported: /// <ul> /// <li>8-bit (unsigned) integer PCM</li><li>16-bit integer PCM (optimal format for XAudio2)</li> /// <li>20-bit integer PCM (either in 24 or 32 bit containers)</li> /// <li>24-bit integer PCM (either in 24 or 32 bit containers)</li><li>32-bit integer PCM</li> /// <li>32-bit float PCM (preferred format after 16-bit integer)</li> /// </ul> /// The number of channels in a source voice must be less than or equal to <see cref="MaxAudioChannels" />. The sample /// rate of a source voice must be between <see cref="MinimumSampleRate" /> and <see cref="MaximumSampleRate" />. /// </param> /// <param name="flags"> /// <see cref="VoiceFlags" /> that specify the behavior of the source voice. A flag can be /// <see cref="VoiceFlags.None" /> or a combination of one or more of the following. /// Possible values are <see cref="VoiceFlags.NoPitch" />, <see cref="VoiceFlags.NoSampleRateConversition" /> and /// <see cref="VoiceFlags.UseFilter" />. <see cref="VoiceFlags.Music" /> is not supported on Windows. /// </param> /// <param name="maxFrequencyRatio"> /// Highest allowable frequency ratio that can be set on this voice. The value for this /// argument must be between <see cref="MinFrequencyRatio" /> and <see cref="MaxFrequencyRatio" />. /// </param> /// <param name="voiceCallback"> /// Client-provided callback interface, <see cref="IXAudio2VoiceCallback" />. This parameter is /// optional and can be null. /// </param> /// <param name="sendList"> /// List of <see cref="VoiceSends" /> structures that describe the set of destination voices for the /// source voice. If <paramref name="sendList" /> is NULL, the send list defaults to a single output to the first mastering /// voice created. /// </param> /// <param name="effectChain"> /// List of <see cref="EffectChain" /> structures that describe an effect chain to use in the /// source voice. This parameter is optional and can be null. /// </param> /// <returns>HRESULT</returns> public override unsafe int CreateSourceVoiceNative( out IntPtr pSourceVoice, IntPtr sourceFormat, VoiceFlags flags, float maxFrequencyRatio, IXAudio2VoiceCallback voiceCallback, VoiceSends?sendList, //out EffectChain?effectChain ) { VoiceSends value0 = sendList.HasValue ? sendList.Value : new VoiceSends(); EffectChain value1 = effectChain.HasValue ? effectChain.Value : new EffectChain(); IntPtr p = IntPtr.Zero; if (voiceCallback != null) { p = Marshal.GetComInterfaceForObject(voiceCallback, typeof(IXAudio2VoiceCallback)); p = Utils.Utils.GetComInterfaceForObjectWithAdjustedVtable(p, 7, 3); } fixed(void *ptr = &pSourceVoice) { return(InteropCalls.CallI(UnsafeBasePtr, ptr, sourceFormat, flags, maxFrequencyRatio, p.ToPointer(), sendList.HasValue ? &value0 : (void *)IntPtr.Zero, effectChain.HasValue ? &value1 : (void *)IntPtr.Zero, ((void **)(*(void **)UnsafeBasePtr))[5])); } }
/// <summary> /// Replaces the effect chain of the voice. /// </summary> /// <param name="effectChain"> /// Describes the new effect chain to use. /// If null is passed, the current effect chain is removed. /// </param> /// <returns>HRESULT</returns> public unsafe int SetEffectChainNative(EffectChain?effectChain) { var ptr = (void *)IntPtr.Zero; //check whether null is passed -> if null is passed, the chain will be removed if (effectChain.HasValue) { EffectChain value = effectChain.Value; ptr = &value; } return(InteropCalls.CallI(UnsafeBasePtr, ptr, ((void **)(*(void **)UnsafeBasePtr))[2])); }
/// <summary> /// Creates and configures a source voice. For more information see /// http://msdn.microsoft.com/en-us/library/windows/desktop/microsoft.directx_sdk.ixaudio2.ixaudio2.createsourcevoice(v=vs.85).aspx. /// </summary> /// <param name="pSourceVoice">If successful, returns a pointer to the new <see cref="XAudio2SourceVoice" /> object.</param> /// <param name="sourceFormat"> /// Pointer to a <see cref="WaveFormat" />. The following formats are supported: /// <ul> /// <li>8-bit (unsigned) integer PCM</li><li>16-bit integer PCM (optimal format for XAudio2)</li> /// <li>20-bit integer PCM (either in 24 or 32 bit containers)</li> /// <li>24-bit integer PCM (either in 24 or 32 bit containers)</li><li>32-bit integer PCM</li> /// <li>32-bit float PCM (preferred format after 16-bit integer)</li> /// </ul> /// The number of channels in a source voice must be less than or equal to <see cref="MaxAudioChannels" />. The sample /// rate of a source voice must be between <see cref="MinimumSampleRate" /> and <see cref="MaximumSampleRate" />. /// </param> /// <param name="flags"> /// <see cref="VoiceFlags" /> that specify the behavior of the source voice. A flag can be /// <see cref="VoiceFlags.None" /> or a combination of one or more of the following. /// Possible values are <see cref="VoiceFlags.NoPitch" />, <see cref="VoiceFlags.NoSampleRateConversition" /> and /// <see cref="VoiceFlags.UseFilter" />. <see cref="VoiceFlags.Music" /> is not supported on Windows. /// </param> /// <param name="maxFrequencyRatio"> /// Highest allowable frequency ratio that can be set on this voice. The value for this /// argument must be between <see cref="MinFrequencyRatio" /> and <see cref="MaxFrequencyRatio" />. /// </param> /// <param name="voiceCallback"> /// Client-provided callback interface, <see cref="IXAudio2VoiceCallback" />. This parameter is /// optional and can be null. /// </param> /// <param name="sendList"> /// List of <see cref="VoiceSends" /> structures that describe the set of destination voices for the /// source voice. If <paramref name="sendList" /> is NULL, the send list defaults to a single output to the first mastering /// voice created. /// </param> /// <param name="effectChain"> /// List of <see cref="EffectChain" /> structures that describe an effect chain to use in the /// source voice. This parameter is optional and can be null. /// </param> /// <returns>HRESULT</returns> public override unsafe int CreateSourceVoiceNative( out IntPtr pSourceVoice, IntPtr sourceFormat, VoiceFlags flags, float maxFrequencyRatio, IXAudio2VoiceCallback voiceCallback, VoiceSends?sendList, //out EffectChain?effectChain ) { VoiceSends value0 = sendList.HasValue ? sendList.Value : new VoiceSends(); EffectChain value1 = effectChain.HasValue ? effectChain.Value : new EffectChain(); IntPtr p = IntPtr.Zero; if (voiceCallback != null) { p = Marshal.GetComInterfaceForObject(voiceCallback, typeof(IXAudio2VoiceCallback)); p = Utils.CSCoreUtils.GetComInterfaceForObjectWithAdjustedVtable(p, 7, 3); } try { fixed(void *ptr = &pSourceVoice) { return(InteropCalls.CallI(UnsafeBasePtr, ptr, sourceFormat, flags, maxFrequencyRatio, p.ToPointer(), sendList.HasValue ? &value0 : (void *)IntPtr.Zero, effectChain.HasValue ? &value1 : (void *)IntPtr.Zero, ((void **)(*(void **)UnsafeBasePtr))[5])); } } finally { if (p != IntPtr.Zero) { //while patching the IUnknown-members out of the vtable, we've made a backup of the release pointer, //which gets called here -> the Marshal.Release method would call any function on index 2 of the vtable //we've patched there Utils.CSCoreUtils.Release(p); //Marshal.Release(p); } } }
/// <summary> /// Creates and configures a submix voice. /// </summary> /// <param name="pSubmixVoice">On success, returns a pointer to the new <see cref="XAudio2SubmixVoice" /> object.</param> /// <param name="inputChannels"> /// Number of channels in the input audio data of the submix voice. The /// <paramref name="inputChannels" /> must be less than or equal to <see cref="MaxAudioChannels" />. /// </param> /// <param name="inputSampleRate"> /// Sample rate of the input audio data of submix voice. This rate must be a multiple of /// <see cref="QuantumDenominator" />. InputSampleRate must be between <see cref="MinimumSampleRate" /> and /// <see cref="MaximumSampleRate" />. /// </param> /// <param name="flags"> /// Flags that specify the behavior of the submix voice. It can be <see cref="VoiceFlags.None" /> or /// <see cref="VoiceFlags.UseFilter" />. /// </param> /// <param name="processingStage"> /// An arbitrary number that specifies when this voice is processed with respect to other /// submix voices, if the XAudio2 engine is running other submix voices. The voice is processed after all other voices /// that include a smaller <paramref name="processingStage" /> value and before all other voices that include a larger /// <paramref name="processingStage" /> value. Voices that include the same <paramref name="processingStage" /> value are /// processed in any order. A submix voice cannot send to another submix voice with a lower or equal /// <paramref name="processingStage" /> value. This prevents audio being lost due to a submix cycle. /// </param> /// <param name="sendList"> /// List of <see cref="VoiceSends" /> structures that describe the set of destination voices for the /// submix voice. If <paramref name="sendList" /> is NULL, the send list will default to a single output to the first /// mastering voice created. /// </param> /// <param name="effectChain"> /// List of <see cref="EffectChain" /> structures that describe an effect chain to use in the /// submix voice. This parameter is optional and can be null. /// </param> /// <returns>HRESULT</returns> public override unsafe int CreateSubmixVoiceNative(out IntPtr pSubmixVoice, int inputChannels, int inputSampleRate, VoiceFlags flags, int processingStage, VoiceSends?sendList, EffectChain?effectChain) { VoiceSends value0 = sendList.HasValue ? sendList.Value : new VoiceSends(); EffectChain value1 = effectChain.HasValue ? effectChain.Value : new EffectChain(); fixed(void *ptr = &pSubmixVoice) { return(InteropCalls.CallI(UnsafeBasePtr, ptr, inputChannels, inputSampleRate, flags, processingStage, sendList.HasValue ? &value0 : (void *)IntPtr.Zero, effectChain.HasValue ? &value1 : (void *)IntPtr.Zero, ((void **)(*(void **)UnsafeBasePtr))[9])); } }
/// <summary> /// Creates and configures a mastering voice. /// </summary> /// <param name="pMasteringVoice">If successful, returns a pointer to the new <see cref="XAudio2MasteringVoice" /> object.</param> /// <param name="inputChannels"> /// Number of channels the mastering voice expects in its input audio. <paramref name="inputChannels" /> must be less than /// or equal to <see cref="MaxAudioChannels" />. /// You can set InputChannels to <see cref="DefaultChannels" />, which causes XAudio2 to try to detect the system /// speaker configuration setup. /// </param> /// <param name="inputSampleRate"> /// Sample rate of the input audio data of the mastering voice. This rate must be a multiple of /// <see cref="QuantumDenominator" />. <paramref name="inputSampleRate" /> must be between <see cref="MinimumSampleRate" /> /// and <see cref="MaximumSampleRate" />. /// You can set InputSampleRate to <see cref="DefaultSampleRate" />, with the default being determined by the current /// platform. /// </param> /// <param name="flags">Flags that specify the behavior of the mastering voice. Must be 0.</param> /// <param name="deviceId"> /// Identifier of the device to receive the output audio. Specifying the default value of NULL /// causes XAudio2 to select the global default audio device. /// </param> /// <param name="effectChain"> /// <see cref="EffectChain" /> structure that describes an effect chain to use in the mastering /// voice, or NULL to use no effects. /// </param> /// <param name="streamCategory">The audio stream category to use for this mastering voice.</param> /// <returns>HRESULT</returns> public override unsafe int CreateMasteringVoiceNative(out IntPtr pMasteringVoice, int inputChannels, int inputSampleRate, int flags, object deviceId, EffectChain?effectChain, AudioStreamCategory streamCategory) { if (deviceId != null && !(deviceId is string)) { throw new ArgumentException("DeviceId has to be a string.", "deviceId"); } var device = deviceId as string; IntPtr pdeviceId = IntPtr.Zero; try { EffectChain value1 = effectChain ?? new EffectChain(); if (device != null) { pdeviceId = Marshal.StringToHGlobalUni(device); fixed(void *ptr = &pMasteringVoice) { return(InteropCalls.CallI( UnsafeBasePtr, ptr, inputChannels, inputSampleRate, flags, (void *)pdeviceId, effectChain.HasValue ? &value1 : (void *)IntPtr.Zero, streamCategory, ((void **)(*(void **)UnsafeBasePtr))[7])); } } finally { if (pdeviceId != IntPtr.Zero) Marshal.FreeHGlobal(pdeviceId); } }
/// <summary> /// Replaces the effect chain of the voice. /// </summary> /// <param name="effectDescriptors"> /// Describes the new effect chain to use. /// If null is passed, the current effect chain is removed. /// </param> public void SetEffectChain(EffectDescriptor[] effectDescriptors) { if (effectDescriptors == null || effectDescriptors.Length == 0) { SetEffectChainNative(null); } else { unsafe { fixed(void *p = &effectDescriptors[0]) { var value = new EffectChain { EffectCount = effectDescriptors.Length, EffectDescriptorsPtr = new IntPtr(p) }; SetEffectChainNative(value); } } } }
/// <summary> /// Creates and configures a source voice. For more information see /// http://msdn.microsoft.com/en-us/library/windows/desktop/microsoft.directx_sdk.ixaudio2.ixaudio2.createsourcevoice(v=vs.85).aspx. /// </summary> /// <param name="sourceFormat"> /// Pointer to a <see cref="WaveFormat" />. The following formats are supported: /// <ul> /// <li>8-bit (unsigned) integer PCM</li><li>16-bit integer PCM (optimal format for XAudio2)</li> /// <li>20-bit integer PCM (either in 24 or 32 bit containers)</li> /// <li>24-bit integer PCM (either in 24 or 32 bit containers)</li><li>32-bit integer PCM</li> /// <li>32-bit float PCM (preferred format after 16-bit integer)</li> /// </ul> /// The number of channels in a source voice must be less than or equal to <see cref="MaxAudioChannels" />. The /// sample rate of a source voice must be between <see cref="MinimumSampleRate" /> and <see cref="MaximumSampleRate" /> /// . /// </param> /// <param name="flags"> /// <see cref="VoiceFlags" /> that specify the behavior of the source voice. A flag can be /// <see cref="VoiceFlags.None" /> or a combination of one or more of the following. /// Possible values are <see cref="VoiceFlags.NoPitch" />, <see cref="VoiceFlags.NoSampleRateConversition" /> and /// <see cref="VoiceFlags.UseFilter" />. <see cref="VoiceFlags.Music" /> is not supported on Windows. /// </param> /// <param name="maxFrequencyRatio"> /// Highest allowable frequency ratio that can be set on this voice. The value for this /// argument must be between <see cref="MinFrequencyRatio" /> and <see cref="MaxFrequencyRatio" />. /// </param> /// <param name="voiceCallback"> /// Client-provided callback interface, <see cref="IXAudio2VoiceCallback" />. This parameter is /// optional and can be null. /// </param> /// <param name="sendList"> /// List of <see cref="VoiceSends" /> structures that describe the set of destination voices for the /// source voice. If <paramref name="sendList" /> is NULL, the send list defaults to a single output to the first /// mastering /// voice created. /// </param> /// <param name="effectChain"> /// List of <see cref="EffectChain" /> structures that describe an effect chain to use in the /// source voice. This parameter is optional and can be null. /// </param> /// <returns>If successful, returns a new <see cref="XAudio2SourceVoice" /> object.</returns> public XAudio2SourceVoice CreateSourceVoice(WaveFormat sourceFormat, VoiceFlags flags, float maxFrequencyRatio, IXAudio2VoiceCallback voiceCallback, VoiceSends? sendList, EffectChain? effectChain) { IntPtr ptr = CreateSourceVoicePtr(sourceFormat, flags, maxFrequencyRatio, voiceCallback, sendList, effectChain); return new XAudio2SourceVoice(ptr, _version); }
/// <summary> /// Creates and configures a submix voice. /// </summary> /// <param name="inputChannels"> /// Number of channels in the input audio data of the submix voice. The /// <paramref name="inputChannels" /> must be less than or equal to <see cref="MaxAudioChannels" />. /// </param> /// <param name="inputSampleRate"> /// Sample rate of the input audio data of submix voice. This rate must be a multiple of /// <see cref="QuantumDenominator" />. InputSampleRate must be between <see cref="MinimumSampleRate" /> and /// <see cref="MaximumSampleRate" />. /// </param> /// <param name="flags"> /// Flags that specify the behavior of the submix voice. It can be <see cref="VoiceFlags.None" /> or /// <see cref="VoiceFlags.UseFilter" />. /// </param> /// <param name="processingStage"> /// An arbitrary number that specifies when this voice is processed with respect to other /// submix voices, if the XAudio2 engine is running other submix voices. The voice is processed after all other voices /// that include a smaller <paramref name="processingStage" /> value and before all other voices that include a larger /// <paramref name="processingStage" /> value. Voices that include the same <paramref name="processingStage" /> value /// are /// processed in any order. A submix voice cannot send to another submix voice with a lower or equal /// <paramref name="processingStage" /> value. This prevents audio being lost due to a submix cycle. /// </param> /// <param name="sendList"> /// List of <see cref="VoiceSends" /> structures that describe the set of destination voices for the /// submix voice. If <paramref name="sendList" /> is NULL, the send list will default to a single output to the first /// mastering voice created. /// </param> /// <param name="effectChain"> /// List of <see cref="EffectChain" /> structures that describe an effect chain to use in the /// submix voice. This parameter is optional and can be null. /// </param> /// <returns>On success, returns a pointer to the new <see cref="XAudio2SubmixVoice" /> object.</returns> public IntPtr CreateSubmixVoicePtr(int inputChannels, int inputSampleRate, VoiceFlags flags, int processingStage, VoiceSends? sendList, EffectChain? effectChain) { IntPtr ptr; int result = CreateSubmixVoiceNative(out ptr, inputChannels, inputSampleRate, flags, processingStage, sendList, effectChain); XAudio2Exception.Try(result, N, "CreateSubmixVoiceNative"); return ptr; }
/// <summary> /// Creates and configures a submix voice. /// </summary> /// <param name="pSubmixVoice">On success, returns a pointer to the new <see cref="XAudio2SubmixVoice" /> object.</param> /// <param name="inputChannels"> /// Number of channels in the input audio data of the submix voice. The /// <paramref name="inputChannels" /> must be less than or equal to <see cref="MaxAudioChannels" />. /// </param> /// <param name="inputSampleRate"> /// Sample rate of the input audio data of submix voice. This rate must be a multiple of /// <see cref="QuantumDenominator" />. InputSampleRate must be between <see cref="MinimumSampleRate" /> and /// <see cref="MaximumSampleRate" />. /// </param> /// <param name="flags"> /// Flags that specify the behavior of the submix voice. It can be <see cref="VoiceFlags.None" /> or /// <see cref="VoiceFlags.UseFilter" />. /// </param> /// <param name="processingStage"> /// An arbitrary number that specifies when this voice is processed with respect to other /// submix voices, if the XAudio2 engine is running other submix voices. The voice is processed after all other voices /// that include a smaller <paramref name="processingStage" /> value and before all other voices that include a larger /// <paramref name="processingStage" /> value. Voices that include the same <paramref name="processingStage" /> value /// are /// processed in any order. A submix voice cannot send to another submix voice with a lower or equal /// <paramref name="processingStage" /> value. This prevents audio being lost due to a submix cycle. /// </param> /// <param name="sendList"> /// List of <see cref="VoiceSends" /> structures that describe the set of destination voices for the /// submix voice. If <paramref name="sendList" /> is NULL, the send list will default to a single output to the first /// mastering voice created. /// </param> /// <param name="effectChain"> /// List of <see cref="EffectChain" /> structures that describe an effect chain to use in the /// submix voice. This parameter is optional and can be null. /// </param> /// <returns>HRESULT</returns> public abstract int CreateSubmixVoiceNative(out IntPtr pSubmixVoice, int inputChannels, int inputSampleRate, VoiceFlags flags, int processingStage, VoiceSends? sendList, EffectChain? effectChain);
/// <summary> /// Creates and configures a submix voice. /// </summary> /// <param name="inputChannels"> /// Number of channels in the input audio data of the submix voice. The /// <paramref name="inputChannels" /> must be less than or equal to <see cref="MaxAudioChannels" />. /// </param> /// <param name="inputSampleRate"> /// Sample rate of the input audio data of submix voice. This rate must be a multiple of /// <see cref="QuantumDenominator" />. InputSampleRate must be between <see cref="MinimumSampleRate" /> and /// <see cref="MaximumSampleRate" />. /// </param> /// <param name="flags"> /// Flags that specify the behavior of the submix voice. It can be <see cref="VoiceFlags.None" /> or /// <see cref="VoiceFlags.UseFilter" />. /// </param> /// <param name="processingStage"> /// An arbitrary number that specifies when this voice is processed with respect to other /// submix voices, if the XAudio2 engine is running other submix voices. The voice is processed after all other voices /// that include a smaller <paramref name="processingStage" /> value and before all other voices that include a larger /// <paramref name="processingStage" /> value. Voices that include the same <paramref name="processingStage" /> value /// are /// processed in any order. A submix voice cannot send to another submix voice with a lower or equal /// <paramref name="processingStage" /> value. This prevents audio being lost due to a submix cycle. /// </param> /// <param name="sendList"> /// List of <see cref="VoiceSends" /> structures that describe the set of destination voices for the /// submix voice. If <paramref name="sendList" /> is NULL, the send list will default to a single output to the first /// mastering voice created. /// </param> /// <param name="effectChain"> /// List of <see cref="EffectChain" /> structures that describe an effect chain to use in the /// submix voice. This parameter is optional and can be null. /// </param> /// <returns>On success, returns a new <see cref="XAudio2SubmixVoice" /> object.</returns> public XAudio2SubmixVoice CreateSubmixVoice(int inputChannels, int inputSampleRate, VoiceFlags flags, int processingStage, VoiceSends? sendList, EffectChain? effectChain) { IntPtr ptr = CreateSubmixVoicePtr(inputChannels, inputSampleRate, flags, processingStage, sendList, effectChain); return new XAudio2SubmixVoice(ptr, _version); }
/// <summary> /// Creates and configures a source voice. For more information see /// http://msdn.microsoft.com/en-us/library/windows/desktop/microsoft.directx_sdk.ixaudio2.ixaudio2.createsourcevoice(v=vs.85).aspx. /// </summary> /// <param name="pSourceVoice">If successful, returns a pointer to the new <see cref="XAudio2SourceVoice" /> object.</param> /// <param name="sourceFormat"> /// Pointer to a <see cref="WaveFormat" />. The following formats are supported: /// <ul> /// <li>8-bit (unsigned) integer PCM</li><li>16-bit integer PCM (optimal format for XAudio2)</li> /// <li>20-bit integer PCM (either in 24 or 32 bit containers)</li> /// <li>24-bit integer PCM (either in 24 or 32 bit containers)</li><li>32-bit integer PCM</li> /// <li>32-bit float PCM (preferred format after 16-bit integer)</li> /// </ul> /// The number of channels in a source voice must be less than or equal to <see cref="MaxAudioChannels" />. The sample /// rate of a source voice must be between <see cref="MinimumSampleRate" /> and <see cref="MaximumSampleRate" />. /// </param> /// <param name="flags"> /// <see cref="VoiceFlags" /> that specify the behavior of the source voice. A flag can be /// <see cref="VoiceFlags.None" /> or a combination of one or more of the following. /// Possible values are <see cref="VoiceFlags.NoPitch" />, <see cref="VoiceFlags.NoSampleRateConversition" /> and /// <see cref="VoiceFlags.UseFilter" />. <see cref="VoiceFlags.Music" /> is not supported on Windows. /// </param> /// <param name="maxFrequencyRatio"> /// Highest allowable frequency ratio that can be set on this voice. The value for this /// argument must be between <see cref="MinFrequencyRatio" /> and <see cref="MaxFrequencyRatio" />. /// </param> /// <param name="voiceCallback"> /// Client-provided callback interface, <see cref="IXAudio2VoiceCallback" />. This parameter is /// optional and can be null. /// </param> /// <param name="sendList"> /// List of <see cref="VoiceSends" /> structures that describe the set of destination voices for the /// source voice. If <paramref name="sendList" /> is NULL, the send list defaults to a single output to the first mastering /// voice created. /// </param> /// <param name="effectChain"> /// List of <see cref="EffectChain" /> structures that describe an effect chain to use in the /// source voice. This parameter is optional and can be null. /// </param> /// <returns>HRESULT</returns> public unsafe override int CreateSourceVoiceNative( out IntPtr pSourceVoice, IntPtr sourceFormat, VoiceFlags flags, float maxFrequencyRatio, IXAudio2VoiceCallback voiceCallback, VoiceSends? sendList, //out EffectChain? effectChain ) { VoiceSends value0 = sendList.HasValue ? sendList.Value : new VoiceSends(); EffectChain value1 = effectChain.HasValue ? effectChain.Value : new EffectChain(); IntPtr p = IntPtr.Zero; if (voiceCallback != null) { p = Marshal.GetComInterfaceForObject(voiceCallback, typeof (IXAudio2VoiceCallback)); p = Utils.Utils.GetComInterfaceForObjectWithAdjustedVtable(p, 7, 3); } try { fixed (void* ptr = &pSourceVoice) { return InteropCalls.CallI(UnsafeBasePtr, ptr, sourceFormat, flags, maxFrequencyRatio, p.ToPointer(), sendList.HasValue ? &value0 : (void*) IntPtr.Zero, effectChain.HasValue ? &value1 : (void*) IntPtr.Zero, ((void**) (*(void**) UnsafeBasePtr))[8]); } } finally { if (p != IntPtr.Zero) { //while patching the IUnknown-members out of the vtable, we've made a backup of the release pointer, //which gets called here -> the Marshal.Release method would call any function on index 2 of the vtable //we've patched there Utils.Utils.Release(p); //Marshal.Release(p); } } }
/// <summary> /// Creates and configures a source voice. For more information see /// http://msdn.microsoft.com/en-us/library/windows/desktop/microsoft.directx_sdk.ixaudio2.ixaudio2.createsourcevoice(v=vs.85).aspx. /// </summary> /// <param name="pSourceVoice">If successful, returns a pointer to the new <see cref="XAudio2SourceVoice" /> object.</param> /// <param name="sourceFormat"> /// Pointer to a <see cref="WaveFormat" />. The following formats are supported: /// <ul> /// <li>8-bit (unsigned) integer PCM</li><li>16-bit integer PCM (optimal format for XAudio2)</li> /// <li>20-bit integer PCM (either in 24 or 32 bit containers)</li> /// <li>24-bit integer PCM (either in 24 or 32 bit containers)</li><li>32-bit integer PCM</li> /// <li>32-bit float PCM (preferred format after 16-bit integer)</li> /// </ul> /// The number of channels in a source voice must be less than or equal to <see cref="MaxAudioChannels" />. The sample /// rate of a source voice must be between <see cref="MinimumSampleRate" /> and <see cref="MaximumSampleRate" />. /// </param> /// <param name="flags"> /// <see cref="VoiceFlags" /> that specify the behavior of the source voice. A flag can be /// <see cref="VoiceFlags.None" /> or a combination of one or more of the following. /// Possible values are <see cref="VoiceFlags.NoPitch" />, <see cref="VoiceFlags.NoSampleRateConversition" /> and /// <see cref="VoiceFlags.UseFilter" />. <see cref="VoiceFlags.Music" /> is not supported on Windows. /// </param> /// <param name="maxFrequencyRatio"> /// Highest allowable frequency ratio that can be set on this voice. The value for this /// argument must be between <see cref="MinFrequencyRatio" /> and <see cref="MaxFrequencyRatio" />. /// </param> /// <param name="voiceCallback"> /// Client-provided callback interface, <see cref="IXAudio2VoiceCallback" />. This parameter is /// optional and can be null. /// </param> /// <param name="sendList"> /// List of <see cref="VoiceSends" /> structures that describe the set of destination voices for the /// source voice. If <paramref name="sendList" /> is NULL, the send list defaults to a single output to the first mastering /// voice created. /// </param> /// <param name="effectChain"> /// List of <see cref="EffectChain" /> structures that describe an effect chain to use in the /// source voice. This parameter is optional and can be null. /// </param> /// <returns>HRESULT</returns> public unsafe override int CreateSourceVoiceNative( out IntPtr pSourceVoice, IntPtr sourceFormat, VoiceFlags flags, float maxFrequencyRatio, IXAudio2VoiceCallback voiceCallback, VoiceSends? sendList, //out EffectChain? effectChain ) { VoiceSends value0 = sendList.HasValue ? sendList.Value : new VoiceSends(); EffectChain value1 = effectChain.HasValue ? effectChain.Value : new EffectChain(); IntPtr p = IntPtr.Zero; if (voiceCallback != null) { p = Marshal.GetComInterfaceForObject(voiceCallback, typeof (IXAudio2VoiceCallback)); p = Utils.Utils.GetComInterfaceForObjectWithAdjustedVtable(p, 7, 3); } fixed (void* ptr = &pSourceVoice) { return InteropCalls.CallI(UnsafeBasePtr, ptr, sourceFormat, flags, maxFrequencyRatio, p.ToPointer(), sendList.HasValue ? &value0 : (void*) IntPtr.Zero, effectChain.HasValue ? &value1 : (void*) IntPtr.Zero, ((void**) (*(void**) UnsafeBasePtr))[8]); } }
/// <summary> /// Creates and configures a mastering voice. /// </summary> /// <param name="inputChannels"> /// Number of channels the mastering voice expects in its input audio. <paramref name="inputChannels" /> must be less /// than /// or equal to <see cref="MaxAudioChannels" />. /// You can set InputChannels to <see cref="DefaultChannels" />, which causes XAudio2 to try to detect the system /// speaker configuration setup. /// </param> /// <param name="inputSampleRate"> /// Sample rate of the input audio data of the mastering voice. This rate must be a multiple of /// <see cref="QuantumDenominator" />. <paramref name="inputSampleRate" /> must be between /// <see cref="MinimumSampleRate" /> /// and <see cref="MaximumSampleRate" />. /// You can set InputSampleRate to <see cref="DefaultSampleRate" />, with the default being determined by the current /// platform. /// </param> /// <param name="flags">Flags that specify the behavior of the mastering voice. Must be 0.</param> /// <param name="device"> /// Identifier of the device to receive the output audio. Specifying the default value of NULL (for XAudio2.8) or 0 (for XAudio2.7) causes /// XAudio2 to select the global default audio device. /// </param> /// <param name="effectChain"> /// <see cref="EffectChain" /> structure that describes an effect chain to use in the mastering /// voice, or NULL to use no effects. /// </param> /// <param name="streamCategory">The audio stream category to use for this mastering voice.</param> /// <returns>If successful, returns a pointer to the new <see cref="XAudio2MasteringVoice" /> object.</returns> public IntPtr CreateMasteringVoicePtr(int inputChannels, int inputSampleRate, int flags, object device, EffectChain? effectChain, AudioStreamCategory streamCategory) { IntPtr ptr; int result = CreateMasteringVoiceNative(out ptr, inputChannels, inputSampleRate, flags, device, effectChain, streamCategory); XAudio2Exception.Try(result, N, "CreateMasteringVoice"); return ptr; }
/// <summary> /// Creates and configures a mastering voice. /// </summary> /// <param name="pMasteringVoice">If successful, returns a pointer to the new <see cref="XAudio2MasteringVoice" /> object.</param> /// <param name="inputChannels"> /// Number of channels the mastering voice expects in its input audio. <paramref name="inputChannels" /> must be less /// than /// or equal to <see cref="MaxAudioChannels" />. /// You can set InputChannels to <see cref="DefaultChannels" />, which causes XAudio2 to try to detect the system /// speaker configuration setup. /// </param> /// <param name="inputSampleRate"> /// Sample rate of the input audio data of the mastering voice. This rate must be a multiple of /// <see cref="QuantumDenominator" />. <paramref name="inputSampleRate" /> must be between /// <see cref="MinimumSampleRate" /> /// and <see cref="MaximumSampleRate" />. /// You can set InputSampleRate to <see cref="DefaultSampleRate" />, with the default being determined by the current /// platform. /// </param> /// <param name="flags">Flags that specify the behavior of the mastering voice. Must be 0.</param> /// <param name="device"> /// Identifier of the device to receive the output audio. Specifying the default value of NULL (for XAudio2.8) or 0 (for XAudio2.7) causes /// XAudio2 to select the global default audio device. /// </param> /// <param name="effectChain"> /// <see cref="EffectChain" /> structure that describes an effect chain to use in the mastering /// voice, or NULL to use no effects. /// </param> /// <param name="streamCategory">The audio stream category to use for this mastering voice.</param> /// <returns>HRESULT</returns> public abstract int CreateMasteringVoiceNative(out IntPtr pMasteringVoice, int inputChannels, int inputSampleRate, int flags, object device, EffectChain? effectChain, AudioStreamCategory streamCategory);
/// <summary> /// Creates and configures a mastering voice. /// </summary> /// <param name="inputChannels"> /// Number of channels the mastering voice expects in its input audio. <paramref name="inputChannels" /> must be less /// than /// or equal to <see cref="MaxAudioChannels" />. /// You can set InputChannels to <see cref="DefaultChannels" />, which causes XAudio2 to try to detect the system /// speaker configuration setup. /// </param> /// <param name="inputSampleRate"> /// Sample rate of the input audio data of the mastering voice. This rate must be a multiple of /// <see cref="QuantumDenominator" />. <paramref name="inputSampleRate" /> must be between /// <see cref="MinimumSampleRate" /> /// and <see cref="MaximumSampleRate" />. /// You can set InputSampleRate to <see cref="DefaultSampleRate" />, with the default being determined by the current /// platform. /// </param> /// <param name="device"> /// Identifier of the device to receive the output audio. Specifying the default value of NULL (for XAudio2.8) or 0 (for XAudio2.7) causes /// XAudio2 to select the global default audio device. /// </param> /// <param name="effectChain"> /// <see cref="EffectChain" /> structure that describes an effect chain to use in the mastering /// voice, or NULL to use no effects. /// </param> /// <param name="streamCategory"><b>XAudio2.8 only:</b> The audio stream category to use for this mastering voice.</param> /// <returns>If successful, returns a new <see cref="XAudio2MasteringVoice" /> object.</returns> public XAudio2MasteringVoice CreateMasteringVoice(int inputChannels, int inputSampleRate, object device, EffectChain? effectChain, AudioStreamCategory streamCategory) { return new XAudio2MasteringVoice(CreateMasteringVoicePtr(inputChannels, inputSampleRate, 0, device, effectChain, streamCategory), _version); }
/// <summary> /// Creates and configures a mastering voice. /// </summary> /// <param name="pMasteringVoice">If successful, returns a pointer to the new <see cref="XAudio2MasteringVoice" /> object.</param> /// <param name="inputChannels"> /// Number of channels the mastering voice expects in its input audio. <paramref name="inputChannels" /> must be less than /// or equal to <see cref="MaxAudioChannels" />. /// You can set InputChannels to <see cref="DefaultChannels" />, which causes XAudio2 to try to detect the system /// speaker configuration setup. /// </param> /// <param name="inputSampleRate"> /// Sample rate of the input audio data of the mastering voice. This rate must be a multiple of /// <see cref="QuantumDenominator" />. <paramref name="inputSampleRate" /> must be between <see cref="MinimumSampleRate" /> /// and <see cref="MaximumSampleRate" />. /// You can set InputSampleRate to <see cref="DefaultSampleRate" />, with the default being determined by the current /// platform. /// </param> /// <param name="flags">Flags that specify the behavior of the mastering voice. Must be 0.</param> /// <param name="deviceId"> /// Identifier of the device to receive the output audio. Specifying the default value of NULL /// causes XAudio2 to select the global default audio device. /// </param> /// <param name="effectChain"> /// <see cref="EffectChain" /> structure that describes an effect chain to use in the mastering /// voice, or NULL to use no effects. /// </param> /// <param name="streamCategory">The audio stream category to use for this mastering voice.</param> /// <returns>HRESULT</returns> public unsafe override int CreateMasteringVoiceNative(out IntPtr pMasteringVoice, int inputChannels, int inputSampleRate, int flags, object deviceId, EffectChain? effectChain, AudioStreamCategory streamCategory) { if (deviceId != null && !(deviceId is string)) throw new ArgumentException("DeviceId has to be a string.", "deviceId"); var device = deviceId as string; IntPtr pdeviceId = IntPtr.Zero; try { EffectChain value1 = effectChain.HasValue ? effectChain.Value : new EffectChain(); if (device != null) pdeviceId = Marshal.StringToHGlobalUni(device); fixed (void* ptr = &pMasteringVoice) { return InteropCalls.CallI( UnsafeBasePtr, ptr, inputChannels, inputSampleRate, flags, (void*) pdeviceId, effectChain.HasValue ? &value1 : (void*) IntPtr.Zero, streamCategory, ((void**) (*(void**) UnsafeBasePtr))[7]); } } finally { if (pdeviceId != IntPtr.Zero) Marshal.FreeHGlobal(pdeviceId); } }
/// <summary> /// Creates and configures a mastering voice. /// </summary> /// <param name="pMasteringVoice">If successful, returns a pointer to the new <see cref="XAudio2MasteringVoice" /> object.</param> /// <param name="inputChannels"> /// Number of channels the mastering voice expects in its input audio. <paramref name="inputChannels" /> must be less than /// or equal to <see cref="MaxAudioChannels" />. /// You can set InputChannels to <see cref="DefaultChannels" />, which causes XAudio2 to try to detect the system /// speaker configuration setup. /// </param> /// <param name="inputSampleRate"> /// Sample rate of the input audio data of the mastering voice. This rate must be a multiple of /// <see cref="QuantumDenominator" />. <paramref name="inputSampleRate" /> must be between <see cref="MinimumSampleRate" /> /// and <see cref="MaximumSampleRate" />. /// You can set InputSampleRate to <see cref="DefaultSampleRate" />, with the default being determined by the current /// platform. /// </param> /// <param name="flags">Flags that specify the behavior of the mastering voice. Must be 0.</param> /// <param name="deviceId"> /// Identifier of the device to receive the output audio. Specifying the default value of 0 (zero) /// causes XAudio2 to select the global default audio device. /// </param> /// <param name="effectChain"> /// <see cref="EffectChain" /> structure that describes an effect chain to use in the mastering /// voice, or NULL to use no effects. /// </param> /// <param name="streamCategory"><b>Not valid for XAudio 2.7.</b></param> /// <returns>HRESULT</returns> public unsafe override int CreateMasteringVoiceNative(out IntPtr pMasteringVoice, int inputChannels, int inputSampleRate, int flags, object deviceId, EffectChain? effectChain, AudioStreamCategory streamCategory) { if (!(deviceId is int)) throw new ArgumentException("DeviceId has to be an integer.", "deviceId"); var device = (int) deviceId; EffectChain value1 = effectChain.HasValue ? effectChain.Value : new EffectChain(); fixed (void* ptr = &pMasteringVoice) { return InteropCalls.CallI( UnsafeBasePtr, ptr, inputChannels, inputSampleRate, flags, device, effectChain.HasValue ? &value1 : (void*) IntPtr.Zero, //streamCategory, ((void**) (*(void**) UnsafeBasePtr))[10]); } }
/// <summary> /// Creates and configures a source voice. For more information see /// http://msdn.microsoft.com/en-us/library/windows/desktop/microsoft.directx_sdk.ixaudio2.ixaudio2.createsourcevoice(v=vs.85).aspx. /// </summary> /// <param name="pSourceVoice">If successful, returns a pointer to the new <see cref="XAudio2SourceVoice" /> object.</param> /// <param name="sourceFormat"> /// Pointer to a <see cref="WaveFormat" />. The following formats are supported: /// <ul> /// <li>8-bit (unsigned) integer PCM</li><li>16-bit integer PCM (optimal format for XAudio2)</li> /// <li>20-bit integer PCM (either in 24 or 32 bit containers)</li> /// <li>24-bit integer PCM (either in 24 or 32 bit containers)</li><li>32-bit integer PCM</li> /// <li>32-bit float PCM (preferred format after 16-bit integer)</li> /// </ul> /// The number of channels in a source voice must be less than or equal to <see cref="MaxAudioChannels" />. The sample /// rate of a source voice must be between <see cref="MinimumSampleRate" /> and <see cref="MaximumSampleRate" />. /// </param> /// <param name="flags"> /// <see cref="VoiceFlags" /> that specify the behavior of the source voice. A flag can be /// <see cref="VoiceFlags.None" /> or a combination of one or more of the following. /// Possible values are <see cref="VoiceFlags.NoPitch" />, <see cref="VoiceFlags.NoSampleRateConversition" /> and /// <see cref="VoiceFlags.UseFilter" />. <see cref="VoiceFlags.Music" /> is not supported on Windows. /// </param> /// <param name="maxFrequencyRatio"> /// Highest allowable frequency ratio that can be set on this voice. The value for this /// argument must be between <see cref="MinFrequencyRatio" /> and <see cref="MaxFrequencyRatio" />. /// </param> /// <param name="voiceCallback"> /// Client-provided callback interface, <see cref="IXAudio2VoiceCallback" />. This parameter is /// optional and can be null. /// </param> /// <param name="sendList"> /// List of <see cref="VoiceSends" /> structures that describe the set of destination voices for the /// source voice. If <paramref name="sendList" /> is NULL, the send list defaults to a single output to the first /// mastering /// voice created. /// </param> /// <param name="effectChain"> /// List of <see cref="EffectChain" /> structures that describe an effect chain to use in the /// source voice. This parameter is optional and can be null. /// </param> /// <returns>HRESULT</returns> public abstract int CreateSourceVoiceNative( out IntPtr pSourceVoice, IntPtr sourceFormat, VoiceFlags flags, float maxFrequencyRatio, IXAudio2VoiceCallback voiceCallback, VoiceSends? sendList, //out EffectChain? effectChain );
/// <summary> /// Creates and configures a submix voice. /// </summary> /// <param name="pSubmixVoice">On success, returns a pointer to the new <see cref="XAudio2SubmixVoice" /> object.</param> /// <param name="inputChannels"> /// Number of channels in the input audio data of the submix voice. The /// <paramref name="inputChannels" /> must be less than or equal to <see cref="MaxAudioChannels" />. /// </param> /// <param name="inputSampleRate"> /// Sample rate of the input audio data of submix voice. This rate must be a multiple of /// <see cref="QuantumDenominator" />. InputSampleRate must be between <see cref="MinimumSampleRate" /> and /// <see cref="MaximumSampleRate" />. /// </param> /// <param name="flags"> /// Flags that specify the behavior of the submix voice. It can be <see cref="VoiceFlags.None" /> or /// <see cref="VoiceFlags.UseFilter" />. /// </param> /// <param name="processingStage"> /// An arbitrary number that specifies when this voice is processed with respect to other /// submix voices, if the XAudio2 engine is running other submix voices. The voice is processed after all other voices /// that include a smaller <paramref name="processingStage" /> value and before all other voices that include a larger /// <paramref name="processingStage" /> value. Voices that include the same <paramref name="processingStage" /> value are /// processed in any order. A submix voice cannot send to another submix voice with a lower or equal /// <paramref name="processingStage" /> value. This prevents audio being lost due to a submix cycle. /// </param> /// <param name="sendList"> /// List of <see cref="VoiceSends" /> structures that describe the set of destination voices for the /// submix voice. If <paramref name="sendList" /> is NULL, the send list will default to a single output to the first /// mastering voice created. /// </param> /// <param name="effectChain"> /// List of <see cref="EffectChain" /> structures that describe an effect chain to use in the /// submix voice. This parameter is optional and can be null. /// </param> /// <returns>HRESULT</returns> public unsafe override int CreateSubmixVoiceNative(out IntPtr pSubmixVoice, int inputChannels, int inputSampleRate, VoiceFlags flags, int processingStage, VoiceSends? sendList, EffectChain? effectChain) { VoiceSends value0 = sendList.HasValue ? sendList.Value : new VoiceSends(); EffectChain value1 = effectChain.HasValue ? effectChain.Value : new EffectChain(); fixed (void* ptr = &pSubmixVoice) { return InteropCalls.CallI(UnsafeBasePtr, ptr, inputChannels, inputSampleRate, flags, processingStage, sendList.HasValue ? &value0 : (void*) IntPtr.Zero, effectChain.HasValue ? &value1 : (void*) IntPtr.Zero, ((void**) (*(void**) UnsafeBasePtr))[9]); } }
/// <summary> /// Creates and configures a source voice. For more information see /// http://msdn.microsoft.com/en-us/library/windows/desktop/microsoft.directx_sdk.ixaudio2.ixaudio2.createsourcevoice(v=vs.85).aspx. /// </summary> /// <param name="sourceFormat"> /// Pointer to a <see cref="WaveFormat" />. The following formats are supported: /// <ul> /// <li>8-bit (unsigned) integer PCM</li><li>16-bit integer PCM (optimal format for XAudio2)</li> /// <li>20-bit integer PCM (either in 24 or 32 bit containers)</li> /// <li>24-bit integer PCM (either in 24 or 32 bit containers)</li><li>32-bit integer PCM</li> /// <li>32-bit float PCM (preferred format after 16-bit integer)</li> /// </ul> /// The number of channels in a source voice must be less than or equal to <see cref="MaxAudioChannels" />. The /// sample rate of a source voice must be between <see cref="MinimumSampleRate" /> and <see cref="MaximumSampleRate" /> /// . /// </param> /// <param name="flags"> /// <see cref="VoiceFlags" /> that specify the behavior of the source voice. A flag can be /// <see cref="VoiceFlags.None" /> or a combination of one or more of the following. /// Possible values are <see cref="VoiceFlags.NoPitch" />, <see cref="VoiceFlags.NoSampleRateConversition" /> and /// <see cref="VoiceFlags.UseFilter" />. <see cref="VoiceFlags.Music" /> is not supported on Windows. /// </param> /// <param name="maxFrequencyRatio"> /// Highest allowable frequency ratio that can be set on this voice. The value for this /// argument must be between <see cref="MinFrequencyRatio" /> and <see cref="MaxFrequencyRatio" />. /// </param> /// <param name="voiceCallback"> /// Client-provided callback interface, <see cref="IXAudio2VoiceCallback" />. This parameter is /// optional and can be null. /// </param> /// <param name="sendList"> /// List of <see cref="VoiceSends" /> structures that describe the set of destination voices for the /// source voice. If <paramref name="sendList" /> is NULL, the send list defaults to a single output to the first /// mastering /// voice created. /// </param> /// <param name="effectChain"> /// List of <see cref="EffectChain" /> structures that describe an effect chain to use in the /// source voice. This parameter is optional and can be null. /// </param> /// <returns>If successful, returns a pointer to the new <see cref="XAudio2SourceVoice" /> object.</returns> public IntPtr CreateSourceVoicePtr(WaveFormat sourceFormat, VoiceFlags flags, float maxFrequencyRatio, IXAudio2VoiceCallback voiceCallback, VoiceSends? sendList, EffectChain? effectChain) { GCHandle hWaveFormat = GCHandle.Alloc(sourceFormat, GCHandleType.Pinned); //todo: do we really need to use GCHandle? try { IntPtr ptr; int result = CreateSourceVoiceNative( out ptr, hWaveFormat.AddrOfPinnedObject(), flags, maxFrequencyRatio, voiceCallback, sendList, effectChain); XAudio2Exception.Try(result, N, "CreateSourceVoice"); return ptr; } finally { if (hWaveFormat.IsAllocated) hWaveFormat.Free(); } }