Example #1
0
 void onUpdate()
 {
     if (lastScrollTime.HasValue && lastScrollTime.Value + 1_000_000 < Stopwatch.GetTimestamp())
     {
         lastScrollTime = null;
         waveformRenderer.clearMinMaxCache();
         Repaint();
     }
 }
Example #2
0
    void OnGUI()
    {
        var clip = selectedAudioClip;
        var text = (clip != null ? clip.name : "No audio clip selected");

        EditorGUILayout.BeginHorizontal();
        GUILayout.Label("Audio editor: " + text);

        if (clip != null && selectionRenderer.hasSelection)
        {
            if (GUILayout.Button("Fade in"))
            {
                volumeGraph.applyFadeIn(selectionRenderer.selectionFrom, selectionRenderer.selectionTo); Repaint();
            }
            if (GUILayout.Button("Fade out"))
            {
                volumeGraph.applyFadeOut(selectionRenderer.selectionFrom, selectionRenderer.selectionTo); Repaint();
            }
            ;
            if (GUILayout.Button("Silence"))
            {
                volumeGraph.applySilence(selectionRenderer.selectionFrom, selectionRenderer.selectionTo); Repaint();
            }

            if (selectionRenderer.hasSelectionRange)
            {
                if (GUILayout.Button("Crop"))
                {
                    cropAudio(selectionRenderer.selectionFrom, selectionRenderer.selectionTo); Repaint();
                }
            }
            else
            {
                if (GUILayout.Button("crop from"))
                {
                    cropAudio(selectionRenderer.selectionFrom, to: 1); Repaint();
                }
                if (GUILayout.Button("crop to"))
                {
                    cropAudio(from: 0, selectionRenderer.selectionTo); Repaint();
                }
            }
        }

        if (GUILayout.Button("Export"))
        {
            exportAudio(); Repaint();
        }

        if (clip != null)
        {
            if (AudioUtilBindings.isClipPlaying(clip))
            {
                if (GUILayout.Button("Stop"))
                {
                    AudioUtilBindings.stopAllClips();
                    isPaused = false;
                }

                if (!isPaused)
                {
                    if (GUILayout.Button("Pause"))
                    {
                        isPaused = true;
                        AudioUtilBindings.pauseClip(clip);
                    }
                }
                else
                {
                    if (GUILayout.Button("Play"))
                    {
                        isPaused = false;
                        AudioUtilBindings.resumeClip(clip);
                    }
                }
            }
            else
            {
                if (GUILayout.Button("Play"))
                {
                    isPaused = false;
                    AudioUtilBindings.stopAllClips();
                    AudioUtilBindings.playClip(clip);

                    if (selectionRenderer.hasSelection)
                    {
                        var sampleFrom = Mathf.FloorToInt(selectionRenderer.selectionFrom * currentAudioData.sampleCount);
                        AudioUtilBindings.setClipSamplePosition(clip, sampleFrom);
                    }
                }
            }

            EditorGUILayout.PrefixLabel("Playback volume");
            playbackVolume = EditorGUILayout.Slider(playbackVolume, 0, 1);
        }

        EditorGUILayout.EndHorizontal();

        if (clip == null)
        {
            return;
        }

        if (AudioUtilBindings.isClipPlaying(clip) && selectionRenderer.hasSelectionRange)
        {
            var currentSample = AudioUtilBindings.getClipSamplePosition(clip);
            var sampleFrom    = Mathf.FloorToInt(selectionRenderer.selectionFrom * currentAudioData.sampleCount);
            var sampleTo      = Mathf.FloorToInt(selectionRenderer.selectionTo * currentAudioData.sampleCount);

            if (currentSample >= sampleTo)
            {
                AudioUtilBindings.stopAllClips();
            }
        }

        var mouseInScrollView = contentRect.containsPoint(Event.current.mousePosition);

        scrollPos = GUI.BeginScrollView(contentRect, scrollPos, scrollRect, alwaysShowHorizontal: true, alwaysShowVertical: false);

        if (volumeGraph.handleMouseEvent(Event.current, channelRect(0, currentAudioData.channels)))
        {
            Event.current.Use();
            Repaint();
        }
        else if (selectionRenderer.handleEvent(Event.current, scrollRect))
        {
            Event.current.Use();
            Repaint();
        }
        else
        {
            switch (Event.current.type)
            {
            case EventType.Repaint: repaint(); break;

            case EventType.ScrollWheel:
                if (mouseInScrollView)
                {
                    // var mouseBefore = Mathf.InverseLerp(0, scrollRect.width, Event.current.mousePosition.x);
                    scale = Mathf.Clamp(scale - Event.current.delta.y * 0.1f, min: 1, max: 40);
                    // var mouseAfter = Mathf.InverseLerp(0, scrollRect.width, Event.current.mousePosition.x);
                    // Debug.Log($"Before: {mouseBefore}, after: {mouseAfter}");
                    // scrollPos.x += (mouseAfter - mouseBefore);

                    lastScrollTime = Stopwatch.GetTimestamp();
                    Repaint();
                    Event.current.Use();
                }
                break;

            case EventType.KeyDown:
                if (Event.current.keyCode == KeyCode.Space)
                {
                    if (clip == null)
                    {
                        break;
                    }

                    Event.current.Use();
                    if (AudioUtilBindings.isClipPlaying(clip))
                    {
                        if (!isPaused)
                        {
                            isPaused = true;
                            AudioUtilBindings.pauseClip(clip);
                        }
                        else
                        {
                            isPaused = false;
                            AudioUtilBindings.resumeClip(clip);
                        }
                    }
                    else
                    {
                        isPaused = false;
                        AudioUtilBindings.stopAllClips();
                        AudioUtilBindings.playClip(clip);

                        if (selectionRenderer.hasSelection)
                        {
                            var sampleFrom = Mathf.FloorToInt(selectionRenderer.selectionFrom * currentAudioData.sampleCount);
                            AudioUtilBindings.setClipSamplePosition(clip, sampleFrom);
                        }
                    }
                }
                else if (Event.current.keyCode == KeyCode.LeftArrow)
                {
                    Event.current.Use();
                    selectionRenderer.moveSelection(seconds: -1, clipLength: clip.length, moveTo: (Event.current.modifiers & EventModifiers.Shift) == 0);
                    Repaint();
                }
                else if (Event.current.keyCode == KeyCode.RightArrow)
                {
                    Event.current.Use();
                    selectionRenderer.moveSelection(seconds: 1, clipLength: clip.length, moveTo: (Event.current.modifiers & EventModifiers.Shift) == 0);
                    Repaint();
                }
                break;
            }
        }

        GUI.EndScrollView();
    }
Example #3
0
        /// <summary>Waits for the associated process to exit.</summary>
        /// <param name="millisecondsTimeout">The amount of time to wait, or -1 to wait indefinitely.</param>
        /// <returns>true if the process exited; false if the timeout occurred.</returns>
        internal bool WaitForExit(int millisecondsTimeout)
        {
            Debug.Assert(!Monitor.IsEntered(_gate));

            // Track the time the we start waiting.
            long startTime = Stopwatch.GetTimestamp();

            // Polling loop
            while (true)
            {
                bool createdTask            = false;
                CancellationTokenSource cts = null;
                Task waitTask;

                // We're in a polling loop... determine how much time remains
                int remainingTimeout = millisecondsTimeout == Timeout.Infinite ?
                                       Timeout.Infinite :
                                       (int)Math.Max(millisecondsTimeout - ((Stopwatch.GetTimestamp() - startTime) / (double)Stopwatch.Frequency * 1000), 0);

                lock (_gate)
                {
                    // If we already know that the process exited, we're done.
                    if (_exited)
                    {
                        return(true);
                    }

                    // If a timeout of 0 was supplied, then we simply need to poll
                    // to see if the process has already exited.
                    if (remainingTimeout == 0)
                    {
                        // If there's currently a wait-in-progress, then we know the other process
                        // hasn't exited (barring races and the polling interval).
                        if (_waitInProgress != null)
                        {
                            return(false);
                        }

                        // No one else is checking for the process' exit... so check.
                        // We're currently holding the _gate lock, so we don't want to
                        // allow CheckForExit to block indefinitely.
                        CheckForExit();
                        return(_exited);
                    }

                    // The process has not yet exited (or at least we don't know it yet)
                    // so we need to wait for it to exit, outside of the lock.
                    // If there's already a wait in progress, we'll do so later
                    // by waiting on that existing task.  Otherwise, we'll spin up
                    // such a task.
                    if (_waitInProgress != null)
                    {
                        waitTask = _waitInProgress;
                    }
                    else
                    {
                        createdTask = true;
                        CancellationToken token = remainingTimeout == Timeout.Infinite ?
                                                  CancellationToken.None :
                                                  (cts = new CancellationTokenSource(remainingTimeout)).Token;
                        waitTask = WaitForExitAsync(token);

                        // PERF NOTE:
                        // At the moment, we never call CheckForExit(true) (which in turn allows
                        // waitpid to block until the child has completed) because we currently call it while
                        // holdling the _gate lock.  This is probably unnecessary in some situations, and in particular
                        // here if remainingTimeout == Timeout.Infinite. In that case, we should be able to set
                        // _waitInProgress to be a TaskCompletionSource task, and then below outside of the lock
                        // we could do a CheckForExit(blockingAllowed:true) and complete the TaskCompletionSource
                        // after that.  We would just need to make sure that there's no risk of the other state
                        // on this instance experiencing torn reads.
                    }
                } // lock(_gate)

                if (createdTask)
                {
                    // We created this task, and it'll get canceled automatically after our timeout.
                    // This Wait should only wake up when either the process has exited or the timeout
                    // has expired.  Either way, we'll loop around again; if the process exited, that'll
                    // be caught first thing in the loop where we check _exited, and if it didn't exit,
                    // our remaining time will be zero, so we'll do a quick remaining check and bail.
                    waitTask.Wait();
                    if (cts != null)
                    {
                        cts.Dispose();
                    }
                }
                else
                {
                    // It's someone else's task.  We'll wait for it to complete. This could complete
                    // either because our remainingTimeout expired or because the task completed,
                    // which could happen because the process exited or because whoever created
                    // that task gave it a timeout.  In any case, we'll loop around again, and the loop
                    // will catch these cases, potentially issuing another wait to make up any
                    // remaining time.
                    waitTask.Wait(remainingTimeout);
                }
            }
        }