Example #1
0
        private void SilenceGenerationRoutine(int bufferSize, WaveFormatEx format)
        {
            try
            {
                var buffer           = new float[bufferSize * format.Channels];
                var bufferDurationMs = bufferSize * 1000 / format.SampleRate;

                while (_continueSilenceThread)
                {
                    _audioClientForRendering.GetCurrentPadding(out var padding);
                    int numFramesAvailable = bufferSize - padding;

                    _audioRenderClient.GetBuffer(numFramesAvailable, out var nativeBuffer);
                    if (nativeBuffer != IntPtr.Zero)
                    {
                        Marshal.Copy(buffer, 0, nativeBuffer, numFramesAvailable * format.Channels);
                        _audioRenderClient.ReleaseBuffer(numFramesAvailable, AudioClientBufferFlags.None);
                    }

                    _stopReading.WaitOne(bufferDurationMs / 2);
                }
            }
            catch (Exception e)
            {
                Log.Warning(e, "Error in Silence generator. Exiting");
            }
        }
Example #2
0
 private void CheckFormat(WaveFormatEx format)
 {
     if (format.WaveFormat != 65534 ||
         format.SubFormat != new Guid("00000003-0000-0010-8000-00aa00389b71"))
     {
         throw new InvalidOperationException($"Unsupported DesktopAudio Format {format.WaveFormat} - {format.SubFormat}");
     }
 }
Example #3
0
        private void StartSilenceGeneration()
        {
            IntPtr mixFormatPtr = IntPtr.Zero;

            try
            {
                Checked(_endpoint.Activate(ref IAudioClientId, ClsCtxEnum.All, IntPtr.Zero, out var obj), "Silence.Activate");
                _audioClientForRendering = (IAudioClient)obj;

                Checked(_audioClientForRendering.GetMixFormat(out mixFormatPtr), "Silence.GetMixFormat");
                WaveFormatEx format = (WaveFormatEx)Marshal.PtrToStructure(mixFormatPtr, typeof(WaveFormatEx));

                CheckFormat(format);

                Checked(_audioClientForRendering.Initialize(AudioClientShareModeEnum.Shared, AudioClientStreamFlagsEnum.None, 10_000_000 * 5, 0, mixFormatPtr, Guid.Empty), "Silence.Initialize");
                Checked(_audioClientForRendering.GetBufferSize(out var bufferSize), "Silence.GetBufferSize");
                Checked(_audioClientForRendering.GetService(IAudioRenderClientId, out var renderObj), "Silence.GetService");

                _audioRenderClient = (IAudioRenderClient)renderObj;

                Checked(_audioClientForRendering.Start(), "Silence.Start");

                _silenceThread      = new Thread(() => SilenceGenerationRoutine(bufferSize, format));
                _silenceThread.Name = "Silence generator";
                _silenceThread.Start();
            }
            catch (Exception e)
            {
                ReleaseComObject(ref _audioClientForRendering);
                ReleaseComObject(ref _audioRenderClient);
                Core.LogError(e, "Faied to StartSilenceGeneration");
            }
            finally
            {
                if (mixFormatPtr != IntPtr.Zero)
                {
                    Marshal.FreeCoTaskMem(mixFormatPtr);
                }
            }
        }
Example #4
0
        public WaveFormatEx Open()
        {
            StopSilenceThread();

            Log.Information("Opening DesktopAudio");
            IMMDeviceEnumerator deviceEnumerator = null;
            IntPtr mixFormatPtr = IntPtr.Zero;

            try
            {
                bool render = true;
                deviceEnumerator = Activator.CreateInstance(typeof(MMDeviceEnumerator)) as IMMDeviceEnumerator;
                var res = deviceEnumerator.GetDefaultAudioEndpoint(
                    render ? DataFlowEnum.Render : DataFlowEnum.Capture,
                    render ? RoleEnum.Console : RoleEnum.Communications,
                    out _endpoint);

                if (render)
                {
                    StartSilenceGeneration();
                }

                Checked(_endpoint.Activate(ref IAudioClientId, ClsCtxEnum.All, IntPtr.Zero, out var obj), "Activate");
                _audioClient = (IAudioClient)obj;

                Checked(_audioClient.GetMixFormat(out mixFormatPtr), "GetMixFormat");
                WaveFormatEx outputFormat = (WaveFormatEx)Marshal.PtrToStructure(mixFormatPtr, typeof(WaveFormatEx));

                if (!render) // for render it is checked in the StartSilenceGeneration();
                {
                    CheckFormat(outputFormat);
                }

                _bytesPerFrame = outputFormat.BlockAlign;

                var flags = AudioClientStreamFlagsEnum.StreamFlagsEventCallback | (render ? AudioClientStreamFlagsEnum.StreamFlagsLoopback : AudioClientStreamFlagsEnum.None);
                Checked(_audioClient.Initialize(AudioClientShareModeEnum.Shared, flags, 10_000_000 * 5, 0, mixFormatPtr, Guid.Empty), "Initialize");

                Checked(_audioClient.GetService(IAudioCaptureClientId, out var captureObj), "GetService");
                _audioCaptureClient = (IAudioCaptureClient)captureObj;

#pragma warning disable CS0618 // Type or member is obsolete
                Checked(_audioClient.SetEventHandle(_dataAvailable.Handle), "SetEventHandle");
#pragma warning restore CS0618 // Type or member is obsolete
                Checked(_audioClient.Start(), "Start");

                return(outputFormat);
            }
            catch (Exception e)
            {
                Core.LogError(e, "Open desktop audio failed");
                StopSilenceThread();

                ReleaseComFields();
                throw;
            }
            finally
            {
                if (mixFormatPtr != IntPtr.Zero)
                {
                    Marshal.FreeCoTaskMem(mixFormatPtr);
                }

                ReleaseComObject(ref deviceEnumerator);
            }
        }