Ejemplo n.º 1
0
        /// <summary>
        /// Code from these gents
        /// https://answers.unity.com/questions/189886/displaying-an-audio-waveform-in-the-editor.html
        /// </summary>
        public Texture2D PaintWaveformSpectrum(AudioClip audio, int width, int height, Color col)
        {
            if (Event.current.type != EventType.Repaint)
            {
                return(null);
            }

            Texture2D tex = new Texture2D(width, height, TextureFormat.RGBA32, false);

            float[] samples = new float[audio.samples * audio.channels];
            // Copy sample data to array
            audio.GetData(samples, 0);

            Color lightShade = new Color(0.3f, 0.3f, 0.3f);
            int   halfHeight = height / 2;

            float leftValue  = AudioPlaybackToolEditor.CalculateZoomedLeftValue();
            float rightValue = AudioPlaybackToolEditor.CalculateZoomedRightValue();

            int leftSide  = Mathf.RoundToInt(leftValue * samples.Length);
            int rightSide = Mathf.RoundToInt(rightValue * samples.Length);

            float zoomLevel = AudioPlaybackToolEditor.scrollZoom / AudioPlaybackToolEditor.MAX_SCROLL_ZOOM;
            int   packSize  = Mathf.RoundToInt((int)samples.Length / (int)width * (float)zoomLevel) + 1;

            int s     = 0;
            int limit = Mathf.Min(rightSide, samples.Length);

            // Build waveform data
            float[] waveform = new float[limit];
            for (int i = leftSide; i < limit; i += packSize)
            {
                waveform[s] = Mathf.Abs(samples[i]);
                s++;
            }

            if (myScript.loopMode == LoopMode.LoopWithLoopPoints)
            {
                float beginning = JSAMExtensions.InverseLerpUnclamped(leftValue, rightValue, myScript.loopStart / audio.length);
                float ending    = JSAMExtensions.InverseLerpUnclamped(leftValue, rightValue, myScript.loopEnd / audio.length);
                float loopStart = beginning * width;
                float loopEnd   = ending * width;

                for (int x = 0; x < width; x++)
                {
                    // Here we limit the scope of the area based on loop points
                    if (x < loopStart || x > loopEnd)
                    {
                        for (int y = 0; y < height; y++)
                        {
                            tex.SetPixel(x, y, Color.black);
                        }
                    }
                    else
                    {
                        for (int y = 0; y < height; y++)
                        {
                            tex.SetPixel(x, y, lightShade);
                        }
                    }
                }
            }
            else
            {
                for (int x = 0; x < width; x++)
                {
                    for (int y = 0; y < height; y++)
                    {
                        tex.SetPixel(x, y, lightShade);
                    }
                }
            }

            for (int x = 0; x < Mathf.Clamp(rightSide, 0, width); x++)
            {
                // Scale the wave vertically relative to half the rect height and the relative volume
                float heightLimit = waveform[x] * halfHeight * myScript.relativeVolume;

                for (int y = (int)heightLimit; y >= 0; y--)
                {
                    Color currentPixelColour = tex.GetPixel(x, halfHeight + y);

                    tex.SetPixel(x, halfHeight + y, currentPixelColour + col * 0.75f);

                    // Get data from upper half offset by 1 unit due to int truncation
                    currentPixelColour = tex.GetPixel(x, halfHeight - (y + 1));
                    // Draw bottom half with data from upper half
                    tex.SetPixel(x, halfHeight - (y + 1), currentPixelColour + col * 0.75f);
                }
            }
            tex.Apply();

            return(tex);
        }
        /// <summary>
        /// Code from these gents
        /// https://answers.unity.com/questions/189886/displaying-an-audio-waveform-in-the-editor.html
        /// </summary>
        public Texture2D PaintWaveformSpectrum(AudioClip audio, int width, int height, Color col)
        {
            if (Event.current.type != EventType.Repaint)
            {
                return(null);
            }

            Texture2D tex = new Texture2D(width, height, TextureFormat.RGBA32, false);

            float[] samples = new float[audio.samples * audio.channels];
            // Copy sample data to array
            audio.GetData(samples, 0);

            float leftValue  = AudioPlaybackToolEditor.CalculateZoomedLeftValue();
            float rightValue = AudioPlaybackToolEditor.CalculateZoomedRightValue();

            int leftSide  = Mathf.RoundToInt(leftValue * samples.Length);
            int rightSide = Mathf.RoundToInt(rightValue * samples.Length);

            float zoomLevel = AudioPlaybackToolEditor.scrollZoom / AudioPlaybackToolEditor.MAX_SCROLL_ZOOM;
            int   packSize  = Mathf.RoundToInt((int)samples.Length / (int)width * (float)zoomLevel) + 1;

            int s     = 0;
            int limit = Mathf.Min(rightSide, samples.Length);

            // Build waveform data
            float[] waveform = new float[limit];
            for (int i = leftSide; i < limit; i += packSize)
            {
                waveform[s] = Mathf.Abs(samples[i]);
                s++;
            }

            float fadeInDuration  = asset.fadeInDuration;
            float fadeOutDuration = asset.fadeOutDuration;

            Color lightShade = new Color(0.3f, 0.3f, 0.3f);
            int   halfHeight = height / 2;

            // The halved height limit of the wave at the left/right extremes
            float fadeStart = leftValue * halfHeight;
            float fadeEnd   = rightValue * halfHeight;

            switch (asset.fadeMode)
            {
            case FadeMode.None:
            {
                for (int x = 0; x < width; x++)
                {
                    for (int y = 0; y < height; y++)
                    {
                        tex.SetPixel(x, y, lightShade);
                    }
                }
            }
            break;

            case FadeMode.FadeIn:     // Paint the fade-in area
            {
                // Scope lol
                {
                    // Scale our fadeIn value by the current zoom
                    float fadeInRelative    = JSAMExtensions.InverseLerpUnclamped(leftValue, rightValue, fadeInDuration);
                    float fadeStartRelative = JSAMExtensions.InverseLerpUnclamped(leftValue, rightValue, 0);

                    // Get the length of the whole fade shape from the scaled fade duration relative to the rect width
                    float fadeWidth = width * fadeInRelative;
                    // Offset the lerp value by how much the left side bar is obscuring the start of the fade
                    int offset = Mathf.RoundToInt(width * Mathf.Abs(fadeStartRelative));

                    // Clamp the limit in case fadeWidth exceeds the right side of the bar
                    for (int x = 0; x + offset < Mathf.Clamp(fadeWidth, 0, width) + offset; x++)
                    {
                        // Paint amount of vertical black depending on progress
                        // Lerp from 0 to half height as those are the extremes we're working with
                        // amountToPaint is the amount of
                        float lerpValue     = (float)(x + offset) / (fadeWidth + offset);
                        int   amountToPaint = (int)Mathf.Lerp(0, halfHeight, lerpValue);
                        for (int y = halfHeight; y >= 0; y--)
                        {
                            switch (amountToPaint)
                            {
                            case 0:
                                tex.SetPixel(x, y, Color.black);
                                break;

                            default:
                                tex.SetPixel(x, y, lightShade);
                                amountToPaint--;
                                break;
                            }
                        }
                        // Paint the same on the lower half
                        for (int y = halfHeight; y < height; y++)
                        {
                            tex.SetPixel(x, halfHeight - y, tex.GetPixel(x, y - halfHeight));
                        }
                    }

                    for (int x = (int)Mathf.Clamp(fadeWidth, 0, width); x < width; x++)
                    {
                        for (int y = 0; y < height; y++)
                        {
                            tex.SetPixel(x, y, lightShade);
                        }
                    }
                }
            }
            break;

            case FadeMode.FadeOut:
            {
                float fadeStartRelative = JSAMExtensions.InverseLerpUnclamped(leftValue, rightValue, 1 - fadeOutDuration);
                int   fadeStartX        = Mathf.RoundToInt(width * fadeStartRelative);

                for (int x = 0; x < fadeStartX; x++)
                {
                    for (int y = 0; y < height; y++)
                    {
                        tex.SetPixel(x, y, lightShade);
                    }
                }

                float fadeEndRelative = JSAMExtensions.InverseLerpUnclamped(leftValue, rightValue, 1);

                float fadeWidth = width * (fadeEndRelative - fadeStartRelative);

                for (int x = fadeStartX; x < width; x++)
                {
                    float lerpValue     = (float)(x - fadeStartX) / (fadeWidth);
                    int   amountToPaint = (int)Mathf.Lerp(halfHeight, 0, lerpValue);
                    for (int y = halfHeight; y >= 0; y--)
                    {
                        switch (amountToPaint)
                        {
                        case 0:
                            tex.SetPixel(x, y, Color.black);
                            break;

                        default:
                            tex.SetPixel(x, y, lightShade);
                            break;
                        }
                        amountToPaint = Mathf.Clamp(amountToPaint - 1, 0, height);
                    }
                    for (int y = halfHeight; y < height; y++)
                    {
                        tex.SetPixel(x, halfHeight - y, tex.GetPixel(x, y - halfHeight));
                    }
                }
            }
            break;

            case FadeMode.FadeInAndOut:
            {
                // Scale our fadeIn value by the current zoom
                float fadeInRelative    = JSAMExtensions.InverseLerpUnclamped(leftValue, rightValue, fadeInDuration);
                float fadeStartRelative = JSAMExtensions.InverseLerpUnclamped(leftValue, rightValue, 0);

                // Get the length of the whole fade shape from the scaled fade duration relative to the rect width
                float fadeWidth = width * fadeInRelative;
                // Offset the lerp value by how much the left side bar is obscuring the start of the fade
                int offset = Mathf.RoundToInt(width * Mathf.Abs(fadeStartRelative));

                for (int x = 0; x + offset < Mathf.Clamp(fadeWidth, 0, width) + offset; x++)
                {
                    float lerpValue     = (float)(x + offset) / (fadeWidth + offset);
                    int   amountToPaint = (int)Mathf.Lerp(0, halfHeight, lerpValue);
                    for (int y = halfHeight; y >= 0; y--)
                    {
                        switch (amountToPaint)
                        {
                        case 0:
                            tex.SetPixel(x, y, Color.black);
                            break;

                        default:
                            tex.SetPixel(x, y, lightShade);
                            break;
                        }
                        amountToPaint = Mathf.Clamp(amountToPaint - 1, 0, height);
                    }
                    for (int y = halfHeight; y < height; y++)
                    {
                        tex.SetPixel(x, halfHeight - y, tex.GetPixel(x, y - halfHeight));
                    }
                }

                fadeStartRelative = JSAMExtensions.InverseLerpUnclamped(leftValue, rightValue, 1 - fadeOutDuration);
                float fadeStartX = width * fadeStartRelative;
                // Paint the middle rectangle
                for (int x = (int)fadeWidth; x < Mathf.Clamp(fadeStartX, 0, width); x++)
                {
                    for (int y = 0; y < height; y++)
                    {
                        tex.SetPixel(x, y, lightShade);
                    }
                }

                float fadeEndRelative = JSAMExtensions.InverseLerpUnclamped(leftValue, rightValue, 1);

                fadeWidth = width * (fadeEndRelative - fadeStartRelative);
                // Paint the right-side triangle
                for (int x = (int)fadeStartX; x < width; x++)
                {
                    float lerpValue     = (float)(x - fadeStartX) / (fadeWidth);
                    int   amountToPaint = (int)Mathf.Lerp(halfHeight, 0, lerpValue);
                    for (int y = halfHeight; y >= 0; y--)
                    {
                        switch (amountToPaint)
                        {
                        case 0:
                            tex.SetPixel(x, y, Color.black);
                            break;

                        default:
                            tex.SetPixel(x, y, lightShade);
                            break;
                        }
                        amountToPaint = Mathf.Clamp(amountToPaint - 1, 0, height);
                    }
                    for (int y = halfHeight; y < height; y++)
                    {
                        tex.SetPixel(x, halfHeight - y, tex.GetPixel(x, y - halfHeight));
                    }
                }
            }
            break;
            }

            for (int x = 0; x < Mathf.Clamp(rightSide, 0, width); x++)
            {
                // Scale the wave vertically relative to half the rect height and the relative volume
                float heightLimit = waveform[x] * halfHeight * asset.relativeVolume;

                for (int y = (int)heightLimit; y >= 0; y--)
                {
                    Color currentPixelColour = tex.GetPixel(x, halfHeight + y);
                    if (currentPixelColour == Color.black)
                    {
                        continue;
                    }

                    tex.SetPixel(x, halfHeight + y, lightShade + col * 0.75f);

                    // Get data from upper half offset by 1 unit due to int truncation
                    tex.SetPixel(x, halfHeight - (y + 1), lightShade + col * 0.75f);
                }
            }
            tex.Apply();

            return(tex);
        }