AudioSwitcher icon indicating copy to clipboard operation
AudioSwitcher copied to clipboard

The CoreAudioController slow at InnerEnumerator.EnumAudioEndpoints

Open EzEddinM opened this issue 1 year ago • 2 comments
trafficstars

The CoreControlAudio is slow because of the InnerEnumerator.EnumAudioEndpoints(EDataFlow.All, EDeviceState.All, out collection); Namespace AudioSwitcher.AudioApi.CoreAudio, class CoreAudioController , Line 46 AudioSwitcher.AudioApi.CoreAudio/CoreAudioController.cs , EDeviceState.All => will it be possible to create a new constructor with EDeviceState as a parameter?

something like this:

public CoreAudioController(EDeviceState eDeviceState)

and change the InnerEnumerator.EnumAudioEndpoints to InnerEnumerator.EnumAudioEndpoints(EDataFlow.All, eDeviceState, out collection);

`Code:

    public CoreAudioController(EDeviceState eDeviceState)
    {
        // ReSharper disable once SuspiciousTypeConversion.Global
        var innerEnumerator = ComObjectFactory.GetDeviceEnumerator();
        _innerEnumeratorPtr = Marshal.GetIUnknownForObject(innerEnumerator);

        if (innerEnumerator == null)
            throw new InvalidComObjectException("No Device Enumerator");

        _innerEnumerator = new ThreadLocal<IMultimediaDeviceEnumerator>(() => Marshal.GetUniqueObjectForIUnknown(_innerEnumeratorPtr) as IMultimediaDeviceEnumerator);

        ComThread.Invoke(() =>
        {
            _systemEvents = new SystemEventNotifcationClient(() => InnerEnumerator);

            _systemEvents.DeviceAdded.Subscribe(x => OnDeviceAdded(x.DeviceId));
            _systemEvents.DeviceRemoved.Subscribe(x => OnDeviceRemoved(x.DeviceId));

            _deviceCache = new HashSet<CoreAudioDevice>();
            IMultimediaDeviceCollection collection;
            InnerEnumerator.EnumAudioEndpoints(EDataFlow.All, eDeviceState, out collection);

            using (var coll = new MultimediaDeviceCollection(collection))
            {
                foreach (var mDev in coll)
                    CacheDevice(mDev);
            }
        });
    }

`

so if you do it we can get the Devices that we need and not all Devices.

Use of the constructor will be somthing like this:

CoreAudioController coreAudioController = new AudioSwitcher.AudioApi.CoreAudio.CoreAudioController(EDeviceState.Active);

EzEddinM avatar Dec 13 '23 14:12 EzEddinM

I'm not sure the actual issue is with fetching all the system devices, but I believe it's in the CacheDevice method, where it's trying to do way too much work.

This constructor is doing far too much, and is really inefficient, in hindsight the work should probably be done during an initialization phase.

Either way, I think the correct solution is to fix the CacheDevice (and probably the AudioDevice constructor)

xenolightning avatar Dec 15 '23 01:12 xenolightning

seeing similar delay

project-sbc avatar Jan 01 '24 12:01 project-sbc