public override void UpdateVisuals()
        {
            // Build a logarithmic spectrum
            float[] scaledSpectrum = new float[NumberOfChunks];
            float   b    = Mathf.Pow(VisualizerCore.SpectrumSize, 1f / NumberOfChunks);
            float   bPow = 1;

            for (int i = 0; i < NumberOfChunks; i++)
            {
                float prevBPow = bPow;
                bPow *= b;
                for (int j = (int)prevBPow; j < bPow - 1 && j < VisualizerCore.SpectrumSize; j++)
                {
                    scaledSpectrum[i] += Mathf.Abs(VisualizerCore.Spectrum(j));
                }
            }

            // Update texture
            Graphics.CopyTexture(_blank, _texture);
            float[] samples = VisualizerCore.Samples(FilterType.Bypass);
            for (int i = 0; i < SampleBarCount && i < samples.Length; i++)
            {
                // Height between 2 and 32
                float heightFrac = Mathf.Clamp01(Mathf.Abs(samples[i])) * SampleMultiplier;
                int   height     = (int)Mathf.Ceil(Mathf.Lerp(SampleBarMinHeight, SampleBarMaxHeight, heightFrac));
                // Draw the rect on the texture buffer
                _texture.SetPixels(
                    SampleBarDistance - height,
                    (SampleBarWidth + SampleBarSeparation) * i,
                    2 * height,
                    SampleBarWidth,
                    Enumerable.Repeat(Color.white, 2 * SampleBarWidth * height).ToArray()
                    );
            }

            // Draw the texture buffer to the texture (no mipmaps)
            _texture.Apply(false);

            // Rotate and jump
            for (int i = 0; i < NumberOfChunks; i++)
            {
                _disks[i].transform.Rotate(Vector3.forward * RotationAmount(i));
                float target = scaledSpectrum[i] * JumpPower;
                float height = Mathf.Clamp(
                    Mathf.Lerp(-_disks[i].transform.localPosition.z, target, FallRate),
                    target,
                    20
                    );
                _disks[i].transform.localPosition = Vector3.back * height;
            }

            _subParent.transform.localRotation =
                Quaternion.Euler(_subRot + new Vector3(5 * Mathf.Sin(Time.time), 5 * Mathf.Sin(Time.time * 1.234f), 0));
        }
        public override void UpdateVisuals()
        {
            float[] low = VisualizerCore.Samples(FilterType.LowPass);
            float[] by  = VisualizerCore.Samples(FilterType.Bypass);

            float sum = 0;

            for (int i = 0; i < low.Length; i++)
            {
                sum += (Mathf.Abs(by[i]) + 0.1f * Mathf.Abs(low[i])) /
                       Mathf.Log(i + 2); // when i < 2, this is divide by zero
            }
            float scaledSum  = sum * Strength;
            float framePower =
                Mathf.Max(scaledSum, Mathf.Lerp(scaledSum, _lastPower, Time.deltaTime)); // Let the bass kick

            _lastPower = framePower;
            _visualEffect.SetFloat("LerpSpeed", framePower);
        }