public void CreateEditorCircCubes()
        {
            if (this.editorCircCubesContainer != null)
            {
                DestroyImmediate(this.editorCircCubesContainer);
                this.editorCircCubesContainer = null;
            }

            // Load EditorOnly scene and find editorCubesParentContainer
            if (!Scenes.AudioVisualizer01_EditorOnly.IsLoaded())
            {
                this.LoadEditorOnlyScene();
            }
            if (this.editorCircCubesContainer == null)
            {
                Scene currentScene = SceneManager.GetActiveScene();
                SceneManager.SetActiveScene(SceneManager.GetSceneByName(Scenes.AudioVisualizer01_EditorOnly.Name));
                this.CreateEditorCircCubesContainer();
                SceneManager.SetActiveScene(currentScene);
            }

            // Create the cubes' parent inside the container in the EditorOnly scene
            this.editorCircCubes = null;

            if (this.circCubeTemplate != null)
            {
                GameObject cubes = SpawnCircCubes((int)this.spectrumVisualizer.FftSize / 2, Vector3.zero, this.circRadius, this.circCubeTemplate.gameObject, this.editorCircCubesContainer.transform);
                this.editorCircCubesContainer.name = EDITOR_CIRC_CUBES_CONTAINER_NAME;
                this.editorCircCubes = new EmissiveScaleUpObject[cubes.transform.childCount];

                SimpleSpectrumProvider spectrumProvider = this.spectrumVisualizer.SpectrumProvider;

                // Randomly create a plausible spectrum for preview.
                for (int i = 0; i < this.editorCircCubes.Length; ++i)
                {
                    this.editorCircCubes[i] = cubes.transform.GetChild(i).gameObject.GetComponent <EmissiveScaleUpObject>();

                    float currFreq           = spectrumProvider.GetFrequency(i);
                    float rndValue           = (float)MathNet.Numerics.Random.MersenneTwister.Default.NextDouble();
                    float g1                 = (float)(+0.0085 * Math.Exp(-Math.Pow(currFreq / 1000 - 2.25, 2) / (2 * 4.60 * 4.60)));
                    float g2                 = (float)(-0.0005 * Math.Exp(-Math.Pow(currFreq / 1000 - 0.00, 2) / (2 * 0.38 * 0.38)));
                    float g3                 = (float)(+0.0046 * Math.Exp(-Math.Pow(currFreq / 1000 - 0.85, 2) / (2 * 0.85 * 0.85)));
                    float g4                 = (float)(-0.0070 * Math.Exp(-Math.Pow(currFreq / 1000 - 3.50, 2) / (2 * 5.00 * 5.00)));
                    float gaussMult          = Math.Abs(g1 + g2 + g3 + g4);
                    float rndScaledValue     = this.spectrumVisualizer.SpectrumScalingFunction(i, rndValue * gaussMult);
                    float clampedScaledValue = Math.Min(rndScaledValue, this.circCubeMaxHeight);
                    this.editorCircCubes[i].Scale(this.circCubeMaxHeight <= 0.0f ? rndScaledValue : Math.Min(rndScaledValue, this.circCubeMaxHeight));
                    this.editorCircCubes[i].SetLightsIntensity(this.CircCubesLightsIntensityFunction(this.circCubeMaxHeight <= 0.0f ? rndScaledValue / this.spectrumVisualizer.ScaledFftDataBuffer.Max() : clampedScaledValue / this.circCubeMaxHeight));
                }
                this.RenameCircCubes(this.editorCircCubes);

                this.UpdateEditorCircCubesParentContainer();
            }
        }
        protected virtual void LoopbackAudioSource_DeviceChanged(object sender, MMDeviceChangedEventArgs e)
        {
            // If the device changes, we need to stop gathering FFT data and re-create the spectrum provider using the new device's format.
            AudioSourceController.LoopbackAudioSource.SingleBlockRead -= this.LoopbackAudioSource_SingleBlockRead;
            this.updateFftDataCoroutine = null;

            if (e.Initialized)
            {
                var deviceFormat = e.Device.DeviceFormat;
                this.spectrumProvider = new SimpleSpectrumProvider(deviceFormat.Channels, deviceFormat.SampleRate, this.fftSize);

                AudioSourceController.LoopbackAudioSource.SingleBlockRead += this.LoopbackAudioSource_SingleBlockRead;
                this.Invoke(() =>
                {
                    this.updateFftDataCoroutine = this.StartCoroutine(this.UpdateFftData());
                }, UPDATE_FFT_INTERVAL * 1.2f);
            }
        }
        private void RenameCircCubes(IReadOnlyList <ScaleUpObject> cubes = null)
        {
#if UNITY_EDITOR
            if (cubes == null)
            {
                cubes = this.circCubes;
            }

            if (cubes != null)
            {
                SimpleSpectrumProvider spectrumProvider = this.spectrumVisualizer.SpectrumProvider;
                for (int i = 0; i < cubes.Count; ++i)
                {
                    cubes[i].gameObject.name = $"Cube{i,-4} @ {spectrumProvider.GetFrequency(i),+5:N0}Hz";
                }
            }
#endif
        }