/// <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)
    {
        Texture2D tex = new Texture2D(width, height, TextureFormat.RGBA32, false);

        float[] samples  = new float[audio.samples];
        float[] waveform = new float[width];
        audio.GetData(samples, 0);

        int packSize = (audio.samples / width) + 1;
        int s        = 0;

        for (int i = 0; i < audio.samples; i += packSize)
        {
            waveform[s] = Mathf.Abs(samples[i]);
            s++;
        }

        AudioFileMusic myScript = (AudioFileMusic)target;

        for (int x = 0; x < width; x++)
        {
            // Here we limit the scope of the area based on loop points
            if (x < waveform.Length * (myScript.loopStart / audio.length) || x > waveform.Length * (myScript.loopEnd / audio.length))
            {
                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, new Color(0.3f, 0.3f, 0.3f));
                }
            }
        }

        for (int x = 0; x < waveform.Length; x++)
        {
            for (int y = 0; y <= waveform[x] * ((float)height * .75f); y++)
            {
                Color currentPixelColour = tex.GetPixel(x, (height / 2) + y);

                tex.SetPixel(x, (height / 2) + y, currentPixelColour + col * 0.75f);

                currentPixelColour = tex.GetPixel(x, (height / 2) - y);
                tex.SetPixel(x, (height / 2) - y, currentPixelColour + col * 0.75f);
            }
        }
        tex.Apply();

        return(tex);
    }
    public override void OnInspectorGUI()
    {
        AudioFileMusic myScript = (AudioFileMusic)target;

        EditorGUILayout.LabelField("The name of this gameObject will be used to refer to audio in script");

        if (myScript.GetFile()[0] == null)
        {
            EditorGUILayout.HelpBox("Error! Add an audio file before running!", MessageType.Error);
        }
        if (myScript.name.Equals("NEW AUDIO FILE") || myScript.name.Equals("None") || myScript.name.Equals("GameObject"))
        {
            EditorGUILayout.HelpBox("Warning! Change the name of the audio file to something different or things will break!", MessageType.Warning);
        }

        DrawDefaultInspector();
    }
    void Update()
    {
        if ((clipPlaying && !clipPaused) || mouseDragging)
        {
            Repaint();

            AudioFileMusic myScript = (AudioFileMusic)target;
            AudioClip      music    = myScript.GetFile();
            float          clipPos  = (float)AudioUtil.GetClipSamplePosition(music) / (float)music.frequency;

            AudioUtil.LoopClip(music, loopClip);
            if (clipPos < myScript.loopStart || clipPos > myScript.loopEnd)
            {
                AudioUtil.SetClipSamplePosition(music, Mathf.CeilToInt(myScript.loopStart * music.frequency));
            }
        }
    }
    public override void OnInspectorGUI()
    {
        AudioFileMusic myScript = (AudioFileMusic)target;

        EditorGUILayout.LabelField("The name of this gameObject will be used to refer to audio in script");

        if (myScript.GetFile() == null)
        {
            EditorGUILayout.HelpBox("Error! Add an audio file before running!", MessageType.Error);
        }
        if (myScript.name.Contains("NEW AUDIO FILE") || myScript.name.Equals("None") || myScript.name.Equals("GameObject"))
        {
            EditorGUILayout.HelpBox("Warning! Change the name of the gameObject to something different or things will break!", MessageType.Warning);
        }

        DrawDefaultInspector();

        if (myScript.useLoopPoints)
        {
            showLoopPointTool = EditorGUILayout.Foldout(showLoopPointTool, "Loop Point Tools");
            if (showLoopPointTool)
            {
                EditorGUILayout.Space();

                EditorGUILayout.LabelField("Customize where music will loop between", EditorStyles.boldLabel);
                int option = (int)myScript.loopPointInputMode;
                option = EditorGUILayout.Popup("Loop Point Setting Mode", option, System.Enum.GetNames(typeof(AudioFileMusic.LoopPointTool)));
                if (option != (int)myScript.loopPointInputMode)
                {
                    Undo.RecordObject(myScript, "Modified loop point tool");
                    myScript.loopPointInputMode = (AudioFileMusic.LoopPointTool)option;
                    EditorUtility.SetDirty(myScript);
                }

                AudioClip music     = myScript.GetFile();
                float     loopStart = myScript.loopStart;
                float     loopEnd   = myScript.loopEnd;

                DrawPlaybackTool(music);

                switch (myScript.loopPointInputMode)
                {
                case AudioFileMusic.LoopPointTool.Slider:
                    GUILayout.Label("Song Duration Samples: " + music.samples);
                    EditorGUILayout.MinMaxSlider(ref loopStart, ref loopEnd, 0, music.length);

                    GUILayout.BeginHorizontal();
                    GUILayout.Label("Loop Point Start: " + TimeToString(loopStart));
                    GUILayout.Label("Loop Point Start (Samples): " + myScript.loopStart * music.frequency);
                    GUILayout.EndHorizontal();

                    GUILayout.BeginHorizontal();
                    GUILayout.Label("Loop Point End: " + TimeToString(loopEnd));
                    GUILayout.Label("Loop Point End (Samples): " + myScript.loopEnd * music.frequency);
                    GUILayout.EndHorizontal();
                    break;

                case AudioFileMusic.LoopPointTool.TimeInput:
                    EditorGUILayout.Space();

                    GUILayout.BeginHorizontal();
                    float theTime = loopStart * 1000f;
                    GUILayout.Label("Loop Point Start:");
                    int minutes = EditorGUILayout.IntField((int)(theTime / 60000f));
                    GUILayout.Label(":");
                    int seconds = EditorGUILayout.IntField((int)(theTime % 60000) / 1000);
                    GUILayout.Label(":");
                    int milliseconds = EditorGUILayout.IntField((int)(theTime % 60000) % 1000);
                    loopStart = (float)minutes * 60f + (float)seconds + (float)milliseconds / 1000f;
                    GUILayout.EndHorizontal();

                    GUILayout.BeginHorizontal();
                    theTime = loopEnd * 1000f;
                    GUILayout.Label("Loop Point End:  ");
                    minutes = EditorGUILayout.IntField((int)theTime / 60000);
                    GUILayout.Label(":");
                    seconds = EditorGUILayout.IntField((int)(theTime % 60000) / 1000);
                    GUILayout.Label(":");
                    milliseconds = EditorGUILayout.IntField((int)(theTime % 60000) % 1000);
                    loopEnd      = (float)minutes * 60f + (float)seconds + (float)milliseconds / 1000f;
                    GUILayout.EndHorizontal();
                    break;

                case AudioFileMusic.LoopPointTool.TimeSamplesInput:
                    GUILayout.Label("Song Duration (Samples): " + music.samples);
                    EditorGUILayout.Space();

                    GUILayout.BeginHorizontal();
                    GUILayout.Label("Loop Point Start:");
                    float samplesStart = EditorGUILayout.FloatField(myScript.loopStart * music.frequency);
                    GUILayout.EndHorizontal();
                    loopStart = samplesStart / music.frequency;

                    GUILayout.BeginHorizontal();
                    GUILayout.Label("Loop Point End:  ");
                    float samplesEnd = EditorGUILayout.FloatField(myScript.loopEnd * music.frequency);
                    GUILayout.EndHorizontal();
                    loopEnd = samplesEnd / music.frequency;
                    break;

                case AudioFileMusic.LoopPointTool.BPMInput /*WithBeats*/:
                    GUILayout.BeginHorizontal();
                    myScript.bpm = EditorGUILayout.IntField("Song BPM: ", myScript.bpm);

                    GUILayout.Label("Song Duration (Beats): " + music.length / (60f / myScript.bpm));

                    GUILayout.EndHorizontal();
                    EditorGUILayout.Space();

                    float startBeat = loopStart / (60f / (float)myScript.bpm);
                    startBeat = EditorGUILayout.FloatField("Starting Beat:", startBeat);

                    float endBeat = loopEnd / (60f / (float)myScript.bpm);
                    endBeat = EditorGUILayout.FloatField("Ending Beat:", endBeat);

                    loopStart = (float)startBeat * 60f / (float)myScript.bpm;
                    loopEnd   = (float)endBeat * 60f / (float)myScript.bpm;
                    break;
                    //case AudioFileMusic.LoopPointTool.BPMInputWithBars:
                    //    GUILayout.BeginHorizontal();
                    //    GUILayout.Label("Song Duration: " + TimeToString(music.length));
                    //    myScript.bpm = EditorGUILayout.IntField("Song BPM: ", myScript.bpm);
                    //    GUILayout.EndHorizontal();
                    //
                    //    int startBar = (int)(loopStart / (60f / (float)myScript.bpm));
                    //    startBar = EditorGUILayout.IntField("Starting Bar:", startBar);
                    //
                    //    int endBar = (int)(loopEnd / (60f / (float)myScript.bpm));
                    //    endBar = EditorGUILayout.IntField("Ending Bar:", endBar);
                    //
                    //    loopStart = startBar * 60f / myScript.bpm;
                    //    loopEnd = endBar * 60f / myScript.bpm;
                    //    break;
                }

                GUIContent buttonText = new GUIContent("Reset Loop Points", "Click to set loop points to the start and end of the track.");
                if (GUILayout.Button(buttonText))
                {
                    loopStart = 0;
                    loopEnd   = music.length;
                }

                if (myScript.loopStart != loopStart || myScript.loopEnd != loopEnd)
                {
                    Undo.RecordObject(myScript, "Modified loop point properties");
                    myScript.loopStart = Mathf.Clamp(loopStart, 0, music.length);
                    myScript.loopEnd   = Mathf.Clamp(loopEnd, 0, Mathf.Ceil(music.length));
                    EditorUtility.SetDirty(myScript);
                }
            }

            serializedObject.ApplyModifiedProperties();
        }
    }