From e93e898df528d013e2e0cfeba22e2b6d76bf99b6 Mon Sep 17 00:00:00 2001
From: Kelebek1 <eeeedddccc@hotmail.co.uk>
Date: Sat, 10 Sep 2022 21:14:03 +0100
Subject: [PATCH] Remove pause callbacks from coretiming

---
 src/audio_core/audio_core.cpp              | 10 -------
 src/audio_core/audio_core.h                |  8 -----
 src/audio_core/renderer/system_manager.cpp | 11 +------
 src/audio_core/renderer/system_manager.h   |  9 ------
 src/audio_core/sink/cubeb_sink.cpp         | 34 +++++-----------------
 src/audio_core/sink/cubeb_sink.h           | 10 -------
 src/audio_core/sink/null_sink.h            |  2 --
 src/audio_core/sink/sdl2_sink.cpp          | 27 ++++-------------
 src/audio_core/sink/sdl2_sink.h            | 10 -------
 src/audio_core/sink/sink.h                 | 10 -------
 src/audio_core/sink/sink_stream.cpp        | 16 ++++++++++
 src/audio_core/sink/sink_stream.h          |  2 --
 src/core/core.cpp                          |  4 ---
 src/core/core_timing.cpp                   | 14 ---------
 src/core/core_timing.h                     |  6 ----
 15 files changed, 29 insertions(+), 144 deletions(-)

diff --git a/src/audio_core/audio_core.cpp b/src/audio_core/audio_core.cpp
index 9feec18296..c845330cd4 100644
--- a/src/audio_core/audio_core.cpp
+++ b/src/audio_core/audio_core.cpp
@@ -47,16 +47,6 @@ AudioRenderer::ADSP::ADSP& AudioCore::GetADSP() {
     return *adsp;
 }
 
-void AudioCore::PauseSinks(const bool pausing) const {
-    if (pausing) {
-        output_sink->PauseStreams();
-        input_sink->PauseStreams();
-    } else {
-        output_sink->UnpauseStreams();
-        input_sink->UnpauseStreams();
-    }
-}
-
 void AudioCore::SetNVDECActive(bool active) {
     nvdec_active = active;
 }
diff --git a/src/audio_core/audio_core.h b/src/audio_core/audio_core.h
index ac9afefaa4..c0a11e6b10 100644
--- a/src/audio_core/audio_core.h
+++ b/src/audio_core/audio_core.h
@@ -57,14 +57,6 @@ public:
      */
     AudioRenderer::ADSP::ADSP& GetADSP();
 
-    /**
-     * Pause the sink. Called from the core.
-     *
-     * @param pausing - Is this pause due to an actual pause, or shutdown?
-     *                  Unfortunately, shutdown also pauses streams, which can cause issues.
-     */
-    void PauseSinks(bool pausing) const;
-
     /**
      * Toggle NVDEC state, used to avoid stall in playback.
      *
diff --git a/src/audio_core/renderer/system_manager.cpp b/src/audio_core/renderer/system_manager.cpp
index bc2dd9e6ec..9c1331e193 100644
--- a/src/audio_core/renderer/system_manager.cpp
+++ b/src/audio_core/renderer/system_manager.cpp
@@ -22,9 +22,7 @@ SystemManager::SystemManager(Core::System& core_)
       thread_event{Core::Timing::CreateEvent(
           "AudioRendererSystemManager", [this](std::uintptr_t, s64 time, std::chrono::nanoseconds) {
               return ThreadFunc2(time);
-          })} {
-    core.CoreTiming().RegisterPauseCallback([this](bool paused) { PauseCallback(paused); });
-}
+          })} {}
 
 SystemManager::~SystemManager() {
     Stop();
@@ -125,11 +123,4 @@ std::optional<std::chrono::nanoseconds> SystemManager::ThreadFunc2(s64 time) {
     return std::nullopt;
 }
 
-void SystemManager::PauseCallback(bool paused) {
-    if (paused && core.IsPoweredOn() && core.IsShuttingDown()) {
-        update.store(true);
-        update.notify_all();
-    }
-}
-
 } // namespace AudioCore::AudioRenderer
diff --git a/src/audio_core/renderer/system_manager.h b/src/audio_core/renderer/system_manager.h
index 1291e9e0ef..81457a3a18 100644
--- a/src/audio_core/renderer/system_manager.h
+++ b/src/audio_core/renderer/system_manager.h
@@ -73,13 +73,6 @@ private:
      */
     std::optional<std::chrono::nanoseconds> ThreadFunc2(s64 time);
 
-    /**
-     * Callback from core timing when pausing, used to detect shutdowns and stop ThreadFunc.
-     *
-     * @param paused - Are we pausing or resuming?
-     */
-    void PauseCallback(bool paused);
-
     enum class StreamState {
         Filling,
         Steady,
@@ -106,8 +99,6 @@ private:
     std::shared_ptr<Core::Timing::EventType> thread_event;
     /// Atomic for main thread to wait on
     std::atomic<bool> update{};
-    /// Current state of the streams
-    StreamState state{StreamState::Filling};
 };
 
 } // namespace AudioCore::AudioRenderer
diff --git a/src/audio_core/sink/cubeb_sink.cpp b/src/audio_core/sink/cubeb_sink.cpp
index 9ae043611d..36b115ad69 100644
--- a/src/audio_core/sink/cubeb_sink.cpp
+++ b/src/audio_core/sink/cubeb_sink.cpp
@@ -129,20 +129,13 @@ public:
      *                 Default false.
      */
     void Start(bool resume = false) override {
-        if (!ctx) {
+        if (!ctx || !paused) {
             return;
         }
 
-        if (resume && was_playing) {
-            if (cubeb_stream_start(stream_backend) != CUBEB_OK) {
-                LOG_CRITICAL(Audio_Sink, "Error starting cubeb stream");
-            }
-            paused = false;
-        } else if (!resume) {
-            if (cubeb_stream_start(stream_backend) != CUBEB_OK) {
-                LOG_CRITICAL(Audio_Sink, "Error starting cubeb stream");
-            }
-            paused = false;
+        paused = false;
+        if (cubeb_stream_start(stream_backend) != CUBEB_OK) {
+            LOG_CRITICAL(Audio_Sink, "Error starting cubeb stream");
         }
     }
 
@@ -151,16 +144,15 @@ public:
      */
     void Stop() override {
         Unstall();
-        if (!ctx) {
+
+        if (!ctx || paused) {
             return;
         }
 
+        paused = true;
         if (cubeb_stream_stop(stream_backend) != CUBEB_OK) {
             LOG_CRITICAL(Audio_Sink, "Error stopping cubeb stream");
         }
-
-        was_playing.store(!paused);
-        paused = true;
     }
 
 private:
@@ -286,18 +278,6 @@ void CubebSink::CloseStreams() {
     sink_streams.clear();
 }
 
-void CubebSink::PauseStreams() {
-    for (auto& stream : sink_streams) {
-        stream->Stop();
-    }
-}
-
-void CubebSink::UnpauseStreams() {
-    for (auto& stream : sink_streams) {
-        stream->Start(true);
-    }
-}
-
 f32 CubebSink::GetDeviceVolume() const {
     if (sink_streams.empty()) {
         return 1.0f;
diff --git a/src/audio_core/sink/cubeb_sink.h b/src/audio_core/sink/cubeb_sink.h
index 91a6480fa6..d98fc08663 100644
--- a/src/audio_core/sink/cubeb_sink.h
+++ b/src/audio_core/sink/cubeb_sink.h
@@ -53,16 +53,6 @@ public:
      */
     void CloseStreams() override;
 
-    /**
-     * Pause all streams.
-     */
-    void PauseStreams() override;
-
-    /**
-     * Unpause all streams.
-     */
-    void UnpauseStreams() override;
-
     /**
      * Get the device volume. Set from calls to the IAudioDevice service.
      *
diff --git a/src/audio_core/sink/null_sink.h b/src/audio_core/sink/null_sink.h
index eab9c3a0cb..1215d3cd25 100644
--- a/src/audio_core/sink/null_sink.h
+++ b/src/audio_core/sink/null_sink.h
@@ -44,8 +44,6 @@ public:
 
     void CloseStream(SinkStream*) override {}
     void CloseStreams() override {}
-    void PauseStreams() override {}
-    void UnpauseStreams() override {}
     f32 GetDeviceVolume() const override {
         return 1.0f;
     }
diff --git a/src/audio_core/sink/sdl2_sink.cpp b/src/audio_core/sink/sdl2_sink.cpp
index 7ee1dd7cd2..1bd001b941 100644
--- a/src/audio_core/sink/sdl2_sink.cpp
+++ b/src/audio_core/sink/sdl2_sink.cpp
@@ -108,17 +108,12 @@ public:
      *                 Default false.
      */
     void Start(bool resume = false) override {
-        if (device == 0) {
+        if (device == 0 || !paused) {
             return;
         }
 
-        if (resume && was_playing) {
-            SDL_PauseAudioDevice(device, 0);
-            paused = false;
-        } else if (!resume) {
-            SDL_PauseAudioDevice(device, 0);
-            paused = false;
-        }
+        paused = false;
+        SDL_PauseAudioDevice(device, 0);
     }
 
     /**
@@ -126,11 +121,11 @@ public:
      */
     void Stop() override {
         Unstall();
-        if (device == 0) {
+        if (device == 0 || paused) {
             return;
         }
-        SDL_PauseAudioDevice(device, 1);
         paused = true;
+        SDL_PauseAudioDevice(device, 1);
     }
 
 private:
@@ -207,18 +202,6 @@ void SDLSink::CloseStreams() {
     sink_streams.clear();
 }
 
-void SDLSink::PauseStreams() {
-    for (auto& stream : sink_streams) {
-        stream->Stop();
-    }
-}
-
-void SDLSink::UnpauseStreams() {
-    for (auto& stream : sink_streams) {
-        stream->Start();
-    }
-}
-
 f32 SDLSink::GetDeviceVolume() const {
     if (sink_streams.empty()) {
         return 1.0f;
diff --git a/src/audio_core/sink/sdl2_sink.h b/src/audio_core/sink/sdl2_sink.h
index 57de9b6c21..9e76dde4fd 100644
--- a/src/audio_core/sink/sdl2_sink.h
+++ b/src/audio_core/sink/sdl2_sink.h
@@ -51,16 +51,6 @@ public:
      */
     void CloseStreams() override;
 
-    /**
-     * Pause all streams.
-     */
-    void PauseStreams() override;
-
-    /**
-     * Unpause all streams.
-     */
-    void UnpauseStreams() override;
-
     /**
      * Get the device volume. Set from calls to the IAudioDevice service.
      *
diff --git a/src/audio_core/sink/sink.h b/src/audio_core/sink/sink.h
index 43d99b62e5..61e3d80cc5 100644
--- a/src/audio_core/sink/sink.h
+++ b/src/audio_core/sink/sink.h
@@ -39,16 +39,6 @@ public:
      */
     virtual void CloseStreams() = 0;
 
-    /**
-     * Pause all streams.
-     */
-    virtual void PauseStreams() = 0;
-
-    /**
-     * Unpause all streams.
-     */
-    virtual void UnpauseStreams() = 0;
-
     /**
      * Create a new sink stream, kept within this sink, with a pointer returned for use.
      * Do not free the returned pointer. When done with the stream, call CloseStream on the sink.
diff --git a/src/audio_core/sink/sink_stream.cpp b/src/audio_core/sink/sink_stream.cpp
index 24636e512b..59a8d69f0f 100644
--- a/src/audio_core/sink/sink_stream.cpp
+++ b/src/audio_core/sink/sink_stream.cpp
@@ -145,6 +145,12 @@ void SinkStream::ProcessAudioIn(std::span<const s16> input_buffer, std::size_t n
     const std::size_t frame_size_bytes = frame_size * sizeof(s16);
     size_t frames_written{0};
 
+    // If we're paused or going to shut down, we don't want to consume buffers as coretiming is
+    // paused and we'll desync, so just return.
+    if (system.IsPaused() || system.IsShuttingDown()) {
+        return;
+    }
+
     if (queued_buffers > max_queue_size) {
         Stall();
     }
@@ -195,6 +201,16 @@ void SinkStream::ProcessAudioOutAndRender(std::span<s16> output_buffer, std::siz
     const std::size_t frame_size_bytes = frame_size * sizeof(s16);
     size_t frames_written{0};
 
+    // If we're paused or going to shut down, we don't want to consume buffers as coretiming is
+    // paused and we'll desync, so just play silence.
+    if (system.IsPaused() || system.IsShuttingDown()) {
+        constexpr std::array<s16, 6> silence{};
+        for (size_t i = frames_written; i < num_frames; i++) {
+            std::memcpy(&output_buffer[i * frame_size], &silence[0], frame_size_bytes);
+        }
+        return;
+    }
+
     // Due to many frames being queued up with nvdec (5 frames or so?), a lot of buffers also get
     // queued up (30+) but not all at once, which causes constant stalling here, so just let the
     // video play out without attempting to stall.
diff --git a/src/audio_core/sink/sink_stream.h b/src/audio_core/sink/sink_stream.h
index db7cff45ec..9aada54f16 100644
--- a/src/audio_core/sink/sink_stream.h
+++ b/src/audio_core/sink/sink_stream.h
@@ -220,8 +220,6 @@ protected:
     u32 device_channels{2};
     /// Is this stream currently paused?
     std::atomic<bool> paused{true};
-    /// Was this stream previously playing?
-    std::atomic<bool> was_playing{false};
     /// Name of this stream
     std::string name{};
 
diff --git a/src/core/core.cpp b/src/core/core.cpp
index e651ce100e..1210928682 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -141,8 +141,6 @@ struct System::Impl {
         core_timing.SyncPause(false);
         is_paused = false;
 
-        audio_core->PauseSinks(false);
-
         return status;
     }
 
@@ -150,8 +148,6 @@ struct System::Impl {
         std::unique_lock<std::mutex> lk(suspend_guard);
         status = SystemResultStatus::Success;
 
-        audio_core->PauseSinks(true);
-
         core_timing.SyncPause(true);
         kernel.Suspend(true);
         is_paused = true;
diff --git a/src/core/core_timing.cpp b/src/core/core_timing.cpp
index 2dbb99c8b0..5375a5d592 100644
--- a/src/core/core_timing.cpp
+++ b/src/core/core_timing.cpp
@@ -73,7 +73,6 @@ void CoreTiming::Shutdown() {
     if (timer_thread) {
         timer_thread->join();
     }
-    pause_callbacks.clear();
     ClearPendingEvents();
     timer_thread.reset();
     has_started = false;
@@ -86,10 +85,6 @@ void CoreTiming::Pause(bool is_paused) {
     if (!is_paused) {
         pause_end_time = GetGlobalTimeNs().count();
     }
-
-    for (auto& cb : pause_callbacks) {
-        cb(is_paused);
-    }
 }
 
 void CoreTiming::SyncPause(bool is_paused) {
@@ -110,10 +105,6 @@ void CoreTiming::SyncPause(bool is_paused) {
     if (!is_paused) {
         pause_end_time = GetGlobalTimeNs().count();
     }
-
-    for (auto& cb : pause_callbacks) {
-        cb(is_paused);
-    }
 }
 
 bool CoreTiming::IsRunning() const {
@@ -219,11 +210,6 @@ void CoreTiming::RemoveEvent(const std::shared_ptr<EventType>& event_type) {
     }
 }
 
-void CoreTiming::RegisterPauseCallback(PauseCallback&& callback) {
-    std::scoped_lock lock{basic_lock};
-    pause_callbacks.emplace_back(std::move(callback));
-}
-
 std::optional<s64> CoreTiming::Advance() {
     std::scoped_lock lock{advance_lock, basic_lock};
     global_timer = GetGlobalTimeNs().count();
diff --git a/src/core/core_timing.h b/src/core/core_timing.h
index 6aa3ae923d..3259397b28 100644
--- a/src/core/core_timing.h
+++ b/src/core/core_timing.h
@@ -22,7 +22,6 @@ namespace Core::Timing {
 /// A callback that may be scheduled for a particular core timing event.
 using TimedCallback = std::function<std::optional<std::chrono::nanoseconds>(
     std::uintptr_t user_data, s64 time, std::chrono::nanoseconds ns_late)>;
-using PauseCallback = std::function<void(bool paused)>;
 
 /// Contains the characteristics of a particular event.
 struct EventType {
@@ -134,9 +133,6 @@ public:
     /// Checks for events manually and returns time in nanoseconds for next event, threadsafe.
     std::optional<s64> Advance();
 
-    /// Register a callback function to be called when coretiming pauses.
-    void RegisterPauseCallback(PauseCallback&& callback);
-
 private:
     struct Event;
 
@@ -176,8 +172,6 @@ private:
     /// Cycle timing
     u64 ticks{};
     s64 downcount{};
-
-    std::vector<PauseCallback> pause_callbacks{};
 };
 
 /// Creates a core timing event with the given name and callback.