internal AudioEndpointVolumeChannels(IAudioEndpointVolume parent)
        {
            int ChannelCount;
            _AudioEndPointVolume = parent;

            ChannelCount = Count;
            _Channels = new AudioEndpointVolumeChannel[ChannelCount];
            for (int i = 0; i < ChannelCount; i++)
            {
                _Channels[i] = new AudioEndpointVolumeChannel(_AudioEndPointVolume, i);
            }
        }
        /// <summary>
        /// Test tone stopped event.
        /// Calculates the recorded volume and proceeds to the next channel/speaker.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void TestToneStopped(object sender, StoppedEventArgs e)
        {
            if (isCanceled)
            {
                return;
            }

            // if all speakers are configured, proceed to the next step
            MMDevice outputAudioDevice = workerThread.GetOutputAudioDevice();

            if (speakerStep >= outputAudioDevice.AudioEndpointVolume.Channels.Count * 2)
            {
                manager.NextStep();
                return;
            }

            // mute all channels to be ready for the next step
            MuteAllChannels();

            // store the average recorded volume
            int channelIndex = speakerStep / 2;

            if (!volumes.ContainsKey((speakerStep - 1) / 2))
            {
                volumes[(speakerStep - 1) / 2]    = new float[3];
                volumes[(speakerStep - 1) / 2][2] = originalChannelVolume[(speakerStep - 1) / 2];
            }

            float volume = testTone.GetAverageCaptureVolume() * volumeScalingFactor;

            manager.SetAudioInputDeviceVolume(volume);
            volumes[(speakerStep - 1) / 2][(speakerStep - 1) % 2] = volume;

            AudioEndpointVolumeChannel audioEndpointVolume = outputAudioDevice.AudioEndpointVolume.Channels[channelIndex];

            if (speakerStep % 2 == 0)
            {
                // configure the next channel
                audioEndpointVolume.VolumeLevelScalar = originalChannelVolume[channelIndex];
                speakerStep++;
                manager.SetInstructions("Calibrating speakers channel " + channelIndex + " - Step 1");
                testTone.Play(TestToneLength, new EventHandler <StoppedEventArgs>(TestToneStopped));
            }
            else
            {
                // repeat the recording with half of the volume to check how much a volume change influences the recorded volume
                audioEndpointVolume.VolumeLevelScalar = originalChannelVolume[channelIndex] / 2;
                speakerStep++;
                manager.SetInstructions("Calibrating speakers channel " + channelIndex + " - Step 2");
                testTone.Play(TestToneLength, new EventHandler <StoppedEventArgs>(TestToneStopped));
            }
        }