private WaveFormat GetFallbackFormat() { WaveFormat correctSampleRateFormat = audioClient.MixFormat; /*WaveFormat.CreateIeeeFloatWaveFormat( * audioClient.MixFormat.SampleRate, * audioClient.MixFormat.Channels);*/ if (!audioClient.IsFormatSupported(shareMode, correctSampleRateFormat)) { // Iterate from Worst to Best Format WaveFormatExtensible[] bestToWorstFormats = { new WaveFormatExtensible( outputFormat.SampleRate, 32, outputFormat.Channels), new WaveFormatExtensible( outputFormat.SampleRate, 24, outputFormat.Channels), new WaveFormatExtensible( outputFormat.SampleRate, 16, outputFormat.Channels), }; // Check from best Format to worst format ( Float32, Int24, Int16 ) for (int i = 0; i < bestToWorstFormats.Length; i++) { correctSampleRateFormat = bestToWorstFormats[i]; if (audioClient.IsFormatSupported(shareMode, correctSampleRateFormat)) { break; } correctSampleRateFormat = null; } // If still null, then test on the PCM16, 2 channels if (correctSampleRateFormat == null) { // Last Last Last Chance (Thanks WASAPI) correctSampleRateFormat = new WaveFormatExtensible(outputFormat.SampleRate, 16, 2); if (!audioClient.IsFormatSupported(shareMode, correctSampleRateFormat)) { throw new NotSupportedException("Can't find a supported format to use"); } } } return(correctSampleRateFormat); }
/// <summary> /// Gets the waveformat of this stream /// </summary> /// <returns>A waveformat (or null if this is not an audio stream)</returns> public WaveFormat GetWaveFormat() { var props = (IWMMediaProps) streamConfig; int size = Math.Max(512, Marshal.SizeOf(typeof (WM_MEDIA_TYPE)) + Marshal.SizeOf(typeof (WaveFormat))); IntPtr buffer = Marshal.AllocCoTaskMem(size); try { props.GetMediaType(buffer, ref size); var mt = (WM_MEDIA_TYPE)Marshal.PtrToStructure(buffer, typeof(WM_MEDIA_TYPE)); if ((mt.majortype == MediaTypes.WMMEDIATYPE_Audio) && // n.b. subtype may not be PCM, but some variation of WM Audio (mt.formattype == MediaTypes.WMFORMAT_WaveFormatEx)) { var fmt = new WaveFormatExtensible(44100, 16, 2); Marshal.PtrToStructure(mt.pbFormat, fmt); return fmt; } return null; } finally { Marshal.FreeCoTaskMem(buffer); } }
/// <summary> /// Initialize for playing the specified wave stream /// </summary> /// <param name="waveProvider">IWaveProvider to play</param> public async Task Init(IWaveProvider waveProvider) { await Activate(); long latencyRefTimes = latencyMilliseconds*10000; outputFormat = waveProvider.WaveFormat; // first attempt uses the WaveFormat from the WaveStream WaveFormatExtensible closestSampleRateFormat; if (!audioClient.IsFormatSupported(shareMode, outputFormat, out closestSampleRateFormat)) { // Use closesSampleRateFormat (in sharedMode, it equals usualy to the audioClient.MixFormat) // See documentation : http://msdn.microsoft.com/en-us/library/ms678737(VS.85).aspx // They say : "In shared mode, the audio engine always supports the mix format" // The MixFormat is more likely to be a WaveFormatExtensible. if (closestSampleRateFormat == null) { WaveFormat correctSampleRateFormat = audioClient.MixFormat; /*WaveFormat.CreateIeeeFloatWaveFormat( audioClient.MixFormat.SampleRate, audioClient.MixFormat.Channels);*/ if (!audioClient.IsFormatSupported(shareMode, correctSampleRateFormat)) { // Iterate from Worst to Best Format WaveFormatExtensible[] bestToWorstFormats = { new WaveFormatExtensible( outputFormat.SampleRate, 32, outputFormat.Channels), new WaveFormatExtensible( outputFormat.SampleRate, 24, outputFormat.Channels), new WaveFormatExtensible( outputFormat.SampleRate, 16, outputFormat.Channels), }; // Check from best Format to worst format ( Float32, Int24, Int16 ) for (int i = 0; i < bestToWorstFormats.Length; i++) { correctSampleRateFormat = bestToWorstFormats[i]; if (audioClient.IsFormatSupported(shareMode, correctSampleRateFormat)) { break; } correctSampleRateFormat = null; } // If still null, then test on the PCM16, 2 channels if (correctSampleRateFormat == null) { // Last Last Last Chance (Thanks WASAPI) correctSampleRateFormat = new WaveFormatExtensible(outputFormat.SampleRate, 16, 2); if (!audioClient.IsFormatSupported(shareMode, correctSampleRateFormat)) { throw new NotSupportedException("Can't find a supported format to use"); } } } outputFormat = correctSampleRateFormat; } else { outputFormat = closestSampleRateFormat; } // just check that we can make it. //using (new MediaFoundationResampler(waveProvider, outputFormat)) { } this.resamplerNeeded = true; } else { resamplerNeeded = false; } this.sourceProvider = waveProvider; // Init Shared or Exclusive if (shareMode == AudioClientShareMode.Shared) { // With EventCallBack and Shared, audioClient.Initialize(shareMode, AudioClientStreamFlags.EventCallback, latencyRefTimes, 0, outputFormat, Guid.Empty); // Get back the effective latency from AudioClient latencyMilliseconds = (int) (audioClient.StreamLatency/10000); } else { // With EventCallBack and Exclusive, both latencies must equals audioClient.Initialize(shareMode, AudioClientStreamFlags.EventCallback, latencyRefTimes, latencyRefTimes, outputFormat, Guid.Empty); } // Create the Wait Event Handle frameEventWaitHandle = NativeMethods.CreateEventEx(IntPtr.Zero, IntPtr.Zero, 0, EventAccess.EVENT_ALL_ACCESS); audioClient.SetEventHandle(frameEventWaitHandle); // Get the RenderClient renderClient = audioClient.AudioRenderClient; }
/// <summary> /// Determines if the specified output format is supported in shared mode /// </summary> /// <param name="shareMode">Share Mode</param> /// <param name="desiredFormat">Desired Format</param> /// <param name="closestMatchFormat">Output The closest match format.</param> /// <returns> /// <c>true</c> if [is format supported] [the specified share mode]; otherwise, <c>false</c>. /// </returns> public bool IsFormatSupported(AudioClientShareMode shareMode, WaveFormat desiredFormat, out WaveFormatExtensible closestMatchFormat) { int hresult = audioClientInterface.IsFormatSupported(shareMode, desiredFormat, out closestMatchFormat); // S_OK is 0, S_FALSE = 1 if (hresult == 0) { // directly supported return true; } if (hresult == 1) { return false; } else if (hresult == (int)AudioClientErrors.UnsupportedFormat) { return false; } else { Marshal.ThrowExceptionForHR(hresult); } // shouldn't get here throw new NotSupportedException("Unknown hresult " + hresult.ToString()); }
/// <summary> /// Initialize for playing the specified wave stream /// </summary> /// <param name="waveProvider">IWaveProvider to play</param> public void Init(IWaveProvider waveProvider) { long latencyRefTimes = latencyMilliseconds * 10000; outputFormat = waveProvider.WaveFormat; // first attempt uses the WaveFormat from the WaveStream WaveFormatExtensible closestSampleRateFormat; if (!audioClient.IsFormatSupported(shareMode, outputFormat, out closestSampleRateFormat)) { // Use closesSampleRateFormat (in sharedMode, it equals usualy to the audioClient.MixFormat) // See documentation : http://msdn.microsoft.com/en-us/library/ms678737(VS.85).aspx // They say : "In shared mode, the audio engine always supports the mix format" // The MixFormat is more likely to be a WaveFormatExtensible. if (closestSampleRateFormat == null) { WaveFormat correctSampleRateFormat = audioClient.MixFormat; /*WaveFormat.CreateIeeeFloatWaveFormat( * audioClient.MixFormat.SampleRate, * audioClient.MixFormat.Channels);*/ if (!audioClient.IsFormatSupported(shareMode, correctSampleRateFormat)) { // Iterate from Worst to Best Format WaveFormatExtensible[] bestToWorstFormats = { new WaveFormatExtensible( outputFormat.SampleRate, 32, outputFormat.Channels), new WaveFormatExtensible( outputFormat.SampleRate, 24, outputFormat.Channels), new WaveFormatExtensible( outputFormat.SampleRate, 16, outputFormat.Channels), }; // Check from best Format to worst format ( Float32, Int24, Int16 ) for (int i = 0; i < bestToWorstFormats.Length; i++) { correctSampleRateFormat = bestToWorstFormats[i]; if (audioClient.IsFormatSupported(shareMode, correctSampleRateFormat)) { break; } correctSampleRateFormat = null; } // If still null, then test on the PCM16, 2 channels if (correctSampleRateFormat == null) { // Last Last Last Chance (Thanks WASAPI) correctSampleRateFormat = new WaveFormatExtensible(outputFormat.SampleRate, 16, 2); if (!audioClient.IsFormatSupported(shareMode, correctSampleRateFormat)) { throw new NotSupportedException("Can't find a supported format to use"); } } } outputFormat = correctSampleRateFormat; } else { outputFormat = closestSampleRateFormat; } // just check that we can make it. using (new ResamplerDmoStream(waveProvider, outputFormat)) { } this.dmoResamplerNeeded = true; } else { dmoResamplerNeeded = false; } this.sourceProvider = waveProvider; // If using EventSync, setup is specific with shareMode if (isUsingEventSync) { // Init Shared or Exclusive if (shareMode == AudioClientShareMode.Shared) { // With EventCallBack and Shared, both latencies must be set to 0 audioClient.Initialize(shareMode, AudioClientStreamFlags.EventCallback, 0, 0, outputFormat, Guid.Empty); // Get back the effective latency from AudioClient latencyMilliseconds = (int)(audioClient.StreamLatency / 10000); } else { // With EventCallBack and Exclusive, both latencies must equals audioClient.Initialize(shareMode, AudioClientStreamFlags.EventCallback, latencyRefTimes, latencyRefTimes, outputFormat, Guid.Empty); } // Create the Wait Event Handle frameEventWaitHandle = new EventWaitHandle(false, EventResetMode.AutoReset); audioClient.SetEventHandle(frameEventWaitHandle.SafeWaitHandle.DangerousGetHandle()); } else { // Normal setup for both sharedMode audioClient.Initialize(shareMode, AudioClientStreamFlags.None, latencyRefTimes, 0, outputFormat, Guid.Empty); } // Get the RenderClient renderClient = audioClient.AudioRenderClient; }
public void CanRequestIfFormatIsSupportedExtensible48000_16bit() { WaveFormatExtensible desiredFormat = new WaveFormatExtensible(48000, 16, 2); Debug.WriteLine(desiredFormat); GetAudioClient().IsFormatSupported(AudioClientShareMode.Shared, desiredFormat); }
public void CanRequestIfFormatIsSupportedExtensible44100ExclusiveMode() { WaveFormatExtensible desiredFormat = new WaveFormatExtensible(44100, 32, 2); Debug.WriteLine(desiredFormat); GetAudioClient().IsFormatSupported(AudioClientShareMode.Exclusive, desiredFormat); }
/// <summary> /// Initialize for playing the specified wave stream /// </summary> /// <param name="waveProvider">IWaveProvider to play</param> public void Init(IWaveProvider waveProvider) { long latencyRefTimes = latencyMilliseconds * 10000; outputFormat = waveProvider.WaveFormat; // first attempt uses the WaveFormat from the WaveStream WaveFormatExtensible closestSampleRateFormat; if (!audioClient.IsFormatSupported(shareMode, outputFormat, out closestSampleRateFormat)) { // Use closesSampleRateFormat (in sharedMode, it equals usualy to the audioClient.MixFormat) // See documentation : http://msdn.microsoft.com/en-us/library/ms678737(VS.85).aspx // They say : "In shared mode, the audio engine always supports the mix format" // The MixFormat is more likely to be a WaveFormatExtensible. if (closestSampleRateFormat == null) { WaveFormat correctSampleRateFormat = audioClient.MixFormat; if (!audioClient.IsFormatSupported(shareMode, correctSampleRateFormat)) { // Iterate from Worst to Best Format WaveFormatExtensible[] bestToWorstFormats = { new WaveFormatExtensible( outputFormat.SampleRate, 32, outputFormat.Channels), new WaveFormatExtensible( outputFormat.SampleRate, 24, outputFormat.Channels), new WaveFormatExtensible( outputFormat.SampleRate, 16, outputFormat.Channels), }; // Check from best Format to worst format ( Float32, Int24, Int16 ) for (int i = 0; i < bestToWorstFormats.Length; i++) { correctSampleRateFormat = bestToWorstFormats[i]; if (audioClient.IsFormatSupported(shareMode, correctSampleRateFormat)) { break; } correctSampleRateFormat = null; } // If still null, then test on the PCM16, 2 channels if (correctSampleRateFormat == null) { // Last Last Last Chance (Thanks WASAPI) correctSampleRateFormat = new WaveFormatExtensible(outputFormat.SampleRate, 16, 2); if (!audioClient.IsFormatSupported(shareMode, correctSampleRateFormat)) { throw new NotSupportedException("Can't find a supported format to use"); } } } outputFormat = correctSampleRateFormat; } else { outputFormat = closestSampleRateFormat; } // just check that we can make it. resamplerDmoStream = new ResamplerDmoStream(waveProvider, outputFormat); sourceProvider = resamplerDmoStream; } else { sourceProvider = waveProvider; } // Normal setup for both sharedMode audioClient.Initialize(shareMode, AudioClientStreamFlags.None, latencyRefTimes, 0, outputFormat, Guid.Empty); // Get the RenderClient renderClient = audioClient.AudioRenderClient; // set up the read buffer bufferFrameCount = audioClient.BufferSize; bytesPerFrame = outputFormat.Channels * outputFormat.BitsPerSample / 8; readBuffer = new byte[bufferFrameCount * bytesPerFrame]; }
/// <summary> /// Initialize for playing the specified wave stream /// </summary> private IWaveProvider Init() { var waveProvider = waveProviderFunc(); long latencyRefTimes = latencyMilliseconds * 10000; outputFormat = waveProvider.WaveFormat; // first attempt uses the WaveFormat from the WaveStream WaveFormatExtensible closestSampleRateFormat; if (!audioClient.IsFormatSupported(shareMode, outputFormat, out closestSampleRateFormat)) { // Use closesSampleRateFormat (in sharedMode, it equals usualy to the audioClient.MixFormat) // See documentation : http://msdn.microsoft.com/en-us/library/ms678737(VS.85).aspx // They say : "In shared mode, the audio engine always supports the mix format" // The MixFormat is more likely to be a WaveFormatExtensible. if (closestSampleRateFormat == null) { WaveFormat correctSampleRateFormat = audioClient.MixFormat; /*WaveFormat.CreateIeeeFloatWaveFormat( * audioClient.MixFormat.SampleRate, * audioClient.MixFormat.Channels);*/ if (!audioClient.IsFormatSupported(shareMode, correctSampleRateFormat)) { // Iterate from Worst to Best Format WaveFormatExtensible[] bestToWorstFormats = { new WaveFormatExtensible( outputFormat.SampleRate, 32, outputFormat.Channels), new WaveFormatExtensible( outputFormat.SampleRate, 24, outputFormat.Channels), new WaveFormatExtensible( outputFormat.SampleRate, 16, outputFormat.Channels), }; // Check from best Format to worst format ( Float32, Int24, Int16 ) for (int i = 0; i < bestToWorstFormats.Length; i++) { correctSampleRateFormat = bestToWorstFormats[i]; if (audioClient.IsFormatSupported(shareMode, correctSampleRateFormat)) { break; } correctSampleRateFormat = null; } // If still null, then test on the PCM16, 2 channels if (correctSampleRateFormat == null) { // Last Last Last Chance (Thanks WASAPI) correctSampleRateFormat = new WaveFormatExtensible(outputFormat.SampleRate, 16, 2); if (!audioClient.IsFormatSupported(shareMode, correctSampleRateFormat)) { throw new NotSupportedException("Can't find a supported format to use"); } } } outputFormat = correctSampleRateFormat; } else { outputFormat = closestSampleRateFormat; } // just check that we can make it. //using (new MediaFoundationResampler(waveProvider, outputFormat)) { } this.resamplerNeeded = true; } else { resamplerNeeded = false; } // Init Shared or Exclusive if (shareMode == AudioClientShareMode.Shared) { // With EventCallBack and Shared, audioClient.Initialize(shareMode, AudioClientStreamFlags.EventCallback, latencyRefTimes, 0, outputFormat, Guid.Empty); // Get back the effective latency from AudioClient. On Windows 10 it can be 0 if (audioClient.StreamLatency > 0) { latencyMilliseconds = (int)(audioClient.StreamLatency / 10000); } } else { // With EventCallBack and Exclusive, both latencies must equals audioClient.Initialize(shareMode, AudioClientStreamFlags.EventCallback, latencyRefTimes, latencyRefTimes, outputFormat, Guid.Empty); } // Create the Wait Event Handle frameEventWaitHandle = NativeMethods.CreateEventExW(IntPtr.Zero, IntPtr.Zero, 0, EventAccess.EVENT_ALL_ACCESS); audioClient.SetEventHandle(frameEventWaitHandle); // Get the RenderClient renderClient = audioClient.AudioRenderClient; return(waveProvider); }
public void Init(IWaveProvider waveProvider) { long num = (long)(this.latencyMilliseconds * 10000); this.outputFormat = waveProvider.WaveFormat; WaveFormatExtensible waveFormatExtensible; if (!this.audioClient.IsFormatSupported(this.shareMode, this.outputFormat, out waveFormatExtensible)) { if (waveFormatExtensible == null) { WaveFormat waveFormat = this.audioClient.MixFormat; if (!this.audioClient.IsFormatSupported(this.shareMode, waveFormat)) { foreach (WaveFormatExtensible waveF in new WaveFormatExtensible[] { new WaveFormatExtensible(this.outputFormat.SampleRate, 32, this.outputFormat.Channels), new WaveFormatExtensible(this.outputFormat.SampleRate, 24, this.outputFormat.Channels), new WaveFormatExtensible(this.outputFormat.SampleRate, 16, this.outputFormat.Channels) }) { if (this.audioClient.IsFormatSupported(this.shareMode, waveF)) { break; } waveFormat = null; } if (waveFormat == null) { waveFormat = new WaveFormatExtensible(this.outputFormat.SampleRate, 16, 2); if (!this.audioClient.IsFormatSupported(this.shareMode, waveFormat)) { throw new NotSupportedException("Can't find a supported format to use"); } } } this.outputFormat = waveFormat; } else { this.outputFormat = waveFormatExtensible; } using (new ResamplerDmoStream(waveProvider, this.outputFormat)) { } this.dmoResamplerNeeded = true; } else { this.dmoResamplerNeeded = false; } this.sourceProvider = waveProvider; if (this.isUsingEventSync) { if (this.shareMode == AudioClientShareMode.Shared) { this.audioClient.Initialize(this.shareMode, AudioClientStreamFlags.EventCallback, 0L, 0L, this.outputFormat, Guid.Empty); this.latencyMilliseconds = (int)(this.audioClient.StreamLatency / 10000L); } else { this.audioClient.Initialize(this.shareMode, AudioClientStreamFlags.EventCallback, num, num, this.outputFormat, Guid.Empty); } this.frameEventWaitHandle = new EventWaitHandle(false, EventResetMode.AutoReset); this.audioClient.SetEventHandle(this.frameEventWaitHandle.SafeWaitHandle.DangerousGetHandle()); } else { this.audioClient.Initialize(this.shareMode, AudioClientStreamFlags.None, num, 0L, this.outputFormat, Guid.Empty); } this.renderClient = this.audioClient.AudioRenderClient; }
/// <summary> /// Initialize for playing the specified wave stream /// </summary> /// <param name="waveProvider">IWaveProvider to play</param> public void Init(IWaveProvider waveProvider) { long latencyRefTimes = latencyMilliseconds * 10000; outputFormat = waveProvider.WaveFormat; // first attempt uses the WaveFormat from the WaveStream WaveFormatExtensible closestSampleRateFormat; if (!audioClient.IsFormatSupported(shareMode, outputFormat, out closestSampleRateFormat)) { // Use closesSampleRateFormat (in sharedMode, it equals usualy to the audioClient.MixFormat) // See documentation : http://msdn.microsoft.com/en-us/library/ms678737(VS.85).aspx // They say : "In shared mode, the audio engine always supports the mix format" // The MixFormat is more likely to be a WaveFormatExtensible. if (closestSampleRateFormat == null) { WaveFormat correctSampleRateFormat = audioClient.MixFormat; /*WaveFormat.CreateIeeeFloatWaveFormat( * audioClient.MixFormat.SampleRate, * audioClient.MixFormat.Channels);*/ if (!audioClient.IsFormatSupported(shareMode, correctSampleRateFormat)) { // Iterate from Worst to Best Format WaveFormatExtensible[] bestToWorstFormats = { new WaveFormatExtensible( outputFormat.SampleRate, 32, outputFormat.Channels), new WaveFormatExtensible( outputFormat.SampleRate, 24, outputFormat.Channels), new WaveFormatExtensible( outputFormat.SampleRate, 16, outputFormat.Channels), }; // Check from best Format to worst format ( Float32, Int24, Int16 ) for (int i = 0; i < bestToWorstFormats.Length; i++) { correctSampleRateFormat = bestToWorstFormats[i]; if (audioClient.IsFormatSupported(shareMode, correctSampleRateFormat)) { break; } correctSampleRateFormat = null; } // If still null and we're using exclusive mode, try to get the device format property. if (correctSampleRateFormat == null && shareMode == AudioClientShareMode.Exclusive) { // Based on https://stackoverflow.com/questions/22616924/wasapi-choosing-a-wave-format-for-exclusive-output byte[] waveFormatBytes = (byte[])mmDevice.Properties[PropertyKeys.PKEY_AudioEngine_DeviceFormat].Value; if (waveFormatBytes != null) { GCHandle handle = GCHandle.Alloc(waveFormatBytes, GCHandleType.Pinned); try { correctSampleRateFormat = (WaveFormatExtensible)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(WaveFormatExtensible)); } finally { handle.Free(); } } } // If still null, then test on the PCM16, 2 channels if (correctSampleRateFormat == null) { // Last Last Last Chance (Thanks WASAPI) correctSampleRateFormat = new WaveFormatExtensible(outputFormat.SampleRate, 16, 2); if (!audioClient.IsFormatSupported(shareMode, correctSampleRateFormat)) { throw new NotSupportedException("Can't find a supported format to use"); } } } outputFormat = correctSampleRateFormat; } else { outputFormat = closestSampleRateFormat; } // just check that we can make it. using (new ResamplerDmoStream(waveProvider, outputFormat)) { } dmoResamplerNeeded = true; } else { dmoResamplerNeeded = false; } sourceProvider = waveProvider; // If using EventSync, setup is specific with shareMode if (isUsingEventSync) { // Init Shared or Exclusive if (shareMode == AudioClientShareMode.Shared) { // With EventCallBack and Shared, both latencies must be set to 0 (update - not sure this is true anymore) // audioClient.Initialize(shareMode, AudioClientStreamFlags.EventCallback, latencyRefTimes, 0, outputFormat, Guid.Empty); // Windows 10 returns 0 from stream latency, resulting in maxing out CPU usage later var streamLatency = audioClient.StreamLatency; if (streamLatency != 0) { // Get back the effective latency from AudioClient latencyMilliseconds = (int)(streamLatency / 10000); } } else { // With EventCallBack and Exclusive, both latencies must equals audioClient.Initialize(shareMode, AudioClientStreamFlags.EventCallback, latencyRefTimes, latencyRefTimes, outputFormat, Guid.Empty); } // Create the Wait Event Handle frameEventWaitHandle = new EventWaitHandle(false, EventResetMode.AutoReset); audioClient.SetEventHandle(frameEventWaitHandle.SafeWaitHandle.DangerousGetHandle()); } else { // Normal setup for both sharedMode audioClient.Initialize(shareMode, AudioClientStreamFlags.None, latencyRefTimes, 0, outputFormat, Guid.Empty); } // Get the RenderClient renderClient = audioClient.AudioRenderClient; }
public void CanRequestIfFormatIsSupportedExtensible44100SharedMode() { WaveFormatExtensible desiredFormat = new WaveFormatExtensible(44100, 32, 2); Console.Write(desiredFormat); GetAudioClient().IsFormatSupported(AudioClientShareMode.Shared, desiredFormat); }
/// <summary> /// Determines if the specified output format is supported in shared mode /// </summary> /// <param name="shareMode">Share Mode</param> /// <param name="desiredFormat">Desired Format</param> /// <param name="closestMatchFormat">Output The closest match format.</param> /// <returns>True if the format is supported</returns> public bool IsFormatSupported(AudioClientShareMode shareMode, WaveFormat desiredFormat, out WaveFormatExtensible closestMatchFormat) { IntPtr pointerToPtr = GetPointerToPointer(); // IntPtr.Zero; // Marshal.AllocHGlobal(Marshal.SizeOf<WaveFormatExtensible>()); closestMatchFormat = null; var pDesiredFormat = desiredFormat.AsInterop(); int hresult = audioClientInterface.IsFormatSupported(shareMode, ref pDesiredFormat, pointerToPtr); var closestMatchPtr = MarshalHelpers.PtrToStructure<IntPtr>(pointerToPtr); if (closestMatchPtr != IntPtr.Zero) { closestMatchFormat = MarshalHelpers.PtrToStructure<WaveFormatExtensibleInterop>(closestMatchPtr); Marshal.FreeCoTaskMem(closestMatchPtr); } Marshal.FreeHGlobal(pointerToPtr); // S_OK is 0, S_FALSE = 1 if (hresult == 0) { // directly supported return true; } if (hresult == 1) { return false; } if (hresult == (int)AudioClientErrors.UnsupportedFormat) { // Succeeded but the specified format is not supported in exclusive mode. return shareMode != AudioClientShareMode.Exclusive; } Marshal.ThrowExceptionForHR(hresult); // shouldn't get here throw new NotSupportedException("Unknown hresult " + hresult); }
/// <summary> /// Initialize for playing the specified wave stream /// </summary> /// <param name="waveProvider">IWaveProvider to play</param> public void Init(IWaveProvider waveProvider) { long latencyRefTimes = latencyMilliseconds * 10000; outputFormat = waveProvider.WaveFormat; // first attempt uses the WaveFormat from the WaveStream WaveFormatExtensible closestSampleRateFormat; if (!audioClient.IsFormatSupported(shareMode, outputFormat, out closestSampleRateFormat)) { // Use closesSampleRateFormat (in sharedMode, it equals usualy to the audioClient.MixFormat) // See documentation : http://msdn.microsoft.com/en-us/library/ms678737(VS.85).aspx // They say : "In shared mode, the audio engine always supports the mix format" // The MixFormat is more likely to be a WaveFormatExtensible. if (closestSampleRateFormat == null) { WaveFormat correctSampleRateFormat = audioClient.MixFormat; /*WaveFormat.CreateIeeeFloatWaveFormat( * audioClient.MixFormat.SampleRate, * audioClient.MixFormat.Channels);*/ if (!audioClient.IsFormatSupported(shareMode, correctSampleRateFormat)) { // Iterate from Worst to Best Format WaveFormatExtensible[] bestToWorstFormats = { new WaveFormatExtensible( outputFormat.SampleRate, 32, outputFormat.Channels), new WaveFormatExtensible( outputFormat.SampleRate, 24, outputFormat.Channels), new WaveFormatExtensible( outputFormat.SampleRate, 16, outputFormat.Channels), }; // Check from best Format to worst format ( Float32, Int24, Int16 ) for (int i = 0; i < bestToWorstFormats.Length; i++) { correctSampleRateFormat = bestToWorstFormats[i]; if (audioClient.IsFormatSupported(shareMode, correctSampleRateFormat)) { break; } correctSampleRateFormat = null; } // If still null, then test on the PCM16, 2 channels if (correctSampleRateFormat == null) { // Last Last Last Chance (Thanks WASAPI) correctSampleRateFormat = new WaveFormatExtensible(outputFormat.SampleRate, 16, 2); if (!audioClient.IsFormatSupported(shareMode, correctSampleRateFormat)) { throw new NotSupportedException("Can't find a supported format to use"); } } } outputFormat = correctSampleRateFormat; } else { outputFormat = closestSampleRateFormat; } // just check that we can make it. using (new ResamplerDmoStream(waveProvider, outputFormat)) { } dmoResamplerNeeded = true; } else { dmoResamplerNeeded = false; } sourceProvider = waveProvider; // If using EventSync, setup is specific with shareMode if (isUsingEventSync) { // Init Shared or Exclusive if (shareMode == AudioClientShareMode.Shared) { // With EventCallBack and Shared, both latencies must be set to 0 (update - not sure this is true anymore) // audioClient.Initialize(shareMode, AudioClientStreamFlags.EventCallback, latencyRefTimes, 0, outputFormat, Guid.Empty); // Windows 10 returns 0 from stream latency, resulting in maxing out CPU usage later var streamLatency = audioClient.StreamLatency; if (streamLatency != 0) { // Get back the effective latency from AudioClient latencyMilliseconds = (int)(streamLatency / 10000); } } else { try { // With EventCallBack and Exclusive, both latencies must equals audioClient.Initialize(shareMode, AudioClientStreamFlags.EventCallback, latencyRefTimes, latencyRefTimes, outputFormat, Guid.Empty); } catch (COMException ex) { // Starting with Windows 7, Initialize can return AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED for a render device. // We should to initialize again. if (ex.ErrorCode != ErrorCodes.AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED) { throw ex; } // Calculate the new latency. long newLatencyRefTimes = (long)(10000000.0 / (double)this.outputFormat.SampleRate * (double)this.audioClient.BufferSize + 0.5); this.audioClient.Dispose(); this.audioClient = this.mmDevice.AudioClient; this.audioClient.Initialize(this.shareMode, AudioClientStreamFlags.EventCallback, newLatencyRefTimes, newLatencyRefTimes, this.outputFormat, Guid.Empty); } } // Create the Wait Event Handle frameEventWaitHandle = new EventWaitHandle(false, EventResetMode.AutoReset); audioClient.SetEventHandle(frameEventWaitHandle.SafeWaitHandle.DangerousGetHandle()); } else { // Normal setup for both sharedMode audioClient.Initialize(shareMode, AudioClientStreamFlags.None, latencyRefTimes, 0, outputFormat, Guid.Empty); } // Get the RenderClient renderClient = audioClient.AudioRenderClient; }
// Token: 0x06000A5C RID: 2652 RVA: 0x0001E2C4 File Offset: 0x0001C4C4 private static bool IsPcmOrIeeeFloat(WaveFormat waveFormat) { WaveFormatExtensible waveFormatExtensible = waveFormat as WaveFormatExtensible; return(waveFormat.Encoding == WaveFormatEncoding.Pcm || waveFormat.Encoding == WaveFormatEncoding.IeeeFloat || (waveFormatExtensible != null && (waveFormatExtensible.SubFormat == AudioSubtypes.MFAudioFormat_PCM || waveFormatExtensible.SubFormat == AudioSubtypes.MFAudioFormat_Float))); }
/// <summary> /// Initialize for playing the specified wave stream /// </summary> /// <param name="waveProvider">IWaveProvider to play</param> public void Init(IWaveProvider waveProvider) { long latencyRefTimes = latencyMilliseconds * 10000; outputFormat = waveProvider.WaveFormat; // first attempt uses the WaveFormat from the WaveStream WaveFormatExtensible closestSampleRateFormat; if (!audioClient.IsFormatSupported(shareMode, outputFormat, out closestSampleRateFormat)) { // Use closesSampleRateFormat (in sharedMode, it equals usualy to the audioClient.MixFormat) // See documentation : http://msdn.microsoft.com/en-us/library/ms678737(VS.85).aspx // They say : "In shared mode, the audio engine always supports the mix format" // The MixFormat is more likely to be a WaveFormatExtensible. if (closestSampleRateFormat == null) { WaveFormat correctSampleRateFormat = audioClient.MixFormat; /*WaveFormat.CreateIeeeFloatWaveFormat( audioClient.MixFormat.SampleRate, audioClient.MixFormat.Channels);*/ if (!audioClient.IsFormatSupported(shareMode, correctSampleRateFormat)) { // Iterate from Worst to Best Format WaveFormatExtensible[] bestToWorstFormats = { new WaveFormatExtensible( outputFormat.SampleRate, 32, outputFormat.Channels), new WaveFormatExtensible( outputFormat.SampleRate, 24, outputFormat.Channels), new WaveFormatExtensible( outputFormat.SampleRate, 16, outputFormat.Channels), }; // Check from best Format to worst format ( Float32, Int24, Int16 ) for (int i = 0; i < bestToWorstFormats.Length; i++ ) { correctSampleRateFormat = bestToWorstFormats[i]; if ( audioClient.IsFormatSupported(shareMode, correctSampleRateFormat) ) { break; } correctSampleRateFormat = null; } // If still null, then test on the PCM16, 2 channels if (correctSampleRateFormat == null) { // Last Last Last Chance (Thanks WASAPI) correctSampleRateFormat = new WaveFormatExtensible(outputFormat.SampleRate, 16, 2); if (!audioClient.IsFormatSupported(shareMode, correctSampleRateFormat)) { throw new NotSupportedException("Can't find a supported format to use"); } } } outputFormat = correctSampleRateFormat; } else { outputFormat = closestSampleRateFormat; } // just check that we can make it. using (new ResamplerDmoStream(waveProvider, outputFormat)) { } this.dmoResamplerNeeded = true; } else { dmoResamplerNeeded = false; } sourceProvider = waveProvider; // If using EventSync, setup is specific with shareMode if (isUsingEventSync) { // Init Shared or Exclusive if (shareMode == AudioClientShareMode.Shared) { // With EventCallBack and Shared, both latencies must be set to 0 (update - not sure this is true anymore) // audioClient.Initialize(shareMode, AudioClientStreamFlags.EventCallback, latencyRefTimes, 0, outputFormat, Guid.Empty); // Windows 10 returns 0 from stream latency, resulting in maxing out CPU usage later var streamLatency = audioClient.StreamLatency; if (streamLatency != 0) { // Get back the effective latency from AudioClient latencyMilliseconds = (int)(streamLatency / 10000); } } else { // With EventCallBack and Exclusive, both latencies must equals audioClient.Initialize(shareMode, AudioClientStreamFlags.EventCallback, latencyRefTimes, latencyRefTimes, outputFormat, Guid.Empty); } // Create the Wait Event Handle frameEventWaitHandle = new EventWaitHandle(false, EventResetMode.AutoReset); audioClient.SetEventHandle(frameEventWaitHandle.SafeWaitHandle.DangerousGetHandle()); } else { // Normal setup for both sharedMode audioClient.Initialize(shareMode, AudioClientStreamFlags.None, latencyRefTimes, 0, outputFormat, Guid.Empty); } // Get the RenderClient renderClient = audioClient.AudioRenderClient; }