Remove pause callbacks from coretiming

merge-requests/60/head
Kelebek1 2022-09-10 21:14:03 +07:00
parent cd4b9bffb2
commit e93e898df5
15 changed files with 29 additions and 144 deletions

@ -47,16 +47,6 @@ AudioRenderer::ADSP::ADSP& AudioCore::GetADSP() {
return *adsp; 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) { void AudioCore::SetNVDECActive(bool active) {
nvdec_active = active; nvdec_active = active;
} }

@ -57,14 +57,6 @@ public:
*/ */
AudioRenderer::ADSP::ADSP& GetADSP(); 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. * Toggle NVDEC state, used to avoid stall in playback.
* *

@ -22,9 +22,7 @@ SystemManager::SystemManager(Core::System& core_)
thread_event{Core::Timing::CreateEvent( thread_event{Core::Timing::CreateEvent(
"AudioRendererSystemManager", [this](std::uintptr_t, s64 time, std::chrono::nanoseconds) { "AudioRendererSystemManager", [this](std::uintptr_t, s64 time, std::chrono::nanoseconds) {
return ThreadFunc2(time); return ThreadFunc2(time);
})} { })} {}
core.CoreTiming().RegisterPauseCallback([this](bool paused) { PauseCallback(paused); });
}
SystemManager::~SystemManager() { SystemManager::~SystemManager() {
Stop(); Stop();
@ -125,11 +123,4 @@ std::optional<std::chrono::nanoseconds> SystemManager::ThreadFunc2(s64 time) {
return std::nullopt; return std::nullopt;
} }
void SystemManager::PauseCallback(bool paused) {
if (paused && core.IsPoweredOn() && core.IsShuttingDown()) {
update.store(true);
update.notify_all();
}
}
} // namespace AudioCore::AudioRenderer } // namespace AudioCore::AudioRenderer

@ -73,13 +73,6 @@ private:
*/ */
std::optional<std::chrono::nanoseconds> ThreadFunc2(s64 time); 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 { enum class StreamState {
Filling, Filling,
Steady, Steady,
@ -106,8 +99,6 @@ private:
std::shared_ptr<Core::Timing::EventType> thread_event; std::shared_ptr<Core::Timing::EventType> thread_event;
/// Atomic for main thread to wait on /// Atomic for main thread to wait on
std::atomic<bool> update{}; std::atomic<bool> update{};
/// Current state of the streams
StreamState state{StreamState::Filling};
}; };
} // namespace AudioCore::AudioRenderer } // namespace AudioCore::AudioRenderer

@ -129,21 +129,14 @@ public:
* Default false. * Default false.
*/ */
void Start(bool resume = false) override { void Start(bool resume = false) override {
if (!ctx) { if (!ctx || !paused) {
return; return;
} }
if (resume && was_playing) { paused = false;
if (cubeb_stream_start(stream_backend) != CUBEB_OK) { if (cubeb_stream_start(stream_backend) != CUBEB_OK) {
LOG_CRITICAL(Audio_Sink, "Error starting cubeb stream"); 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;
}
} }
/** /**
@ -151,16 +144,15 @@ public:
*/ */
void Stop() override { void Stop() override {
Unstall(); Unstall();
if (!ctx) {
if (!ctx || paused) {
return; return;
} }
paused = true;
if (cubeb_stream_stop(stream_backend) != CUBEB_OK) { if (cubeb_stream_stop(stream_backend) != CUBEB_OK) {
LOG_CRITICAL(Audio_Sink, "Error stopping cubeb stream"); LOG_CRITICAL(Audio_Sink, "Error stopping cubeb stream");
} }
was_playing.store(!paused);
paused = true;
} }
private: private:
@ -286,18 +278,6 @@ void CubebSink::CloseStreams() {
sink_streams.clear(); 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 { f32 CubebSink::GetDeviceVolume() const {
if (sink_streams.empty()) { if (sink_streams.empty()) {
return 1.0f; return 1.0f;

@ -53,16 +53,6 @@ public:
*/ */
void CloseStreams() override; 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. * Get the device volume. Set from calls to the IAudioDevice service.
* *

@ -44,8 +44,6 @@ public:
void CloseStream(SinkStream*) override {} void CloseStream(SinkStream*) override {}
void CloseStreams() override {} void CloseStreams() override {}
void PauseStreams() override {}
void UnpauseStreams() override {}
f32 GetDeviceVolume() const override { f32 GetDeviceVolume() const override {
return 1.0f; return 1.0f;
} }

@ -108,17 +108,12 @@ public:
* Default false. * Default false.
*/ */
void Start(bool resume = false) override { void Start(bool resume = false) override {
if (device == 0) { if (device == 0 || !paused) {
return; return;
} }
if (resume && was_playing) {
SDL_PauseAudioDevice(device, 0);
paused = false; paused = false;
} else if (!resume) {
SDL_PauseAudioDevice(device, 0); SDL_PauseAudioDevice(device, 0);
paused = false;
}
} }
/** /**
@ -126,11 +121,11 @@ public:
*/ */
void Stop() override { void Stop() override {
Unstall(); Unstall();
if (device == 0) { if (device == 0 || paused) {
return; return;
} }
SDL_PauseAudioDevice(device, 1);
paused = true; paused = true;
SDL_PauseAudioDevice(device, 1);
} }
private: private:
@ -207,18 +202,6 @@ void SDLSink::CloseStreams() {
sink_streams.clear(); 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 { f32 SDLSink::GetDeviceVolume() const {
if (sink_streams.empty()) { if (sink_streams.empty()) {
return 1.0f; return 1.0f;

@ -51,16 +51,6 @@ public:
*/ */
void CloseStreams() override; 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. * Get the device volume. Set from calls to the IAudioDevice service.
* *

@ -39,16 +39,6 @@ public:
*/ */
virtual void CloseStreams() = 0; 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. * 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. * Do not free the returned pointer. When done with the stream, call CloseStream on the sink.

@ -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); const std::size_t frame_size_bytes = frame_size * sizeof(s16);
size_t frames_written{0}; 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) { if (queued_buffers > max_queue_size) {
Stall(); 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); const std::size_t frame_size_bytes = frame_size * sizeof(s16);
size_t frames_written{0}; 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 // 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 // queued up (30+) but not all at once, which causes constant stalling here, so just let the
// video play out without attempting to stall. // video play out without attempting to stall.

@ -220,8 +220,6 @@ protected:
u32 device_channels{2}; u32 device_channels{2};
/// Is this stream currently paused? /// Is this stream currently paused?
std::atomic<bool> paused{true}; std::atomic<bool> paused{true};
/// Was this stream previously playing?
std::atomic<bool> was_playing{false};
/// Name of this stream /// Name of this stream
std::string name{}; std::string name{};

@ -141,8 +141,6 @@ struct System::Impl {
core_timing.SyncPause(false); core_timing.SyncPause(false);
is_paused = false; is_paused = false;
audio_core->PauseSinks(false);
return status; return status;
} }
@ -150,8 +148,6 @@ struct System::Impl {
std::unique_lock<std::mutex> lk(suspend_guard); std::unique_lock<std::mutex> lk(suspend_guard);
status = SystemResultStatus::Success; status = SystemResultStatus::Success;
audio_core->PauseSinks(true);
core_timing.SyncPause(true); core_timing.SyncPause(true);
kernel.Suspend(true); kernel.Suspend(true);
is_paused = true; is_paused = true;

@ -73,7 +73,6 @@ void CoreTiming::Shutdown() {
if (timer_thread) { if (timer_thread) {
timer_thread->join(); timer_thread->join();
} }
pause_callbacks.clear();
ClearPendingEvents(); ClearPendingEvents();
timer_thread.reset(); timer_thread.reset();
has_started = false; has_started = false;
@ -86,10 +85,6 @@ void CoreTiming::Pause(bool is_paused) {
if (!is_paused) { if (!is_paused) {
pause_end_time = GetGlobalTimeNs().count(); pause_end_time = GetGlobalTimeNs().count();
} }
for (auto& cb : pause_callbacks) {
cb(is_paused);
}
} }
void CoreTiming::SyncPause(bool is_paused) { void CoreTiming::SyncPause(bool is_paused) {
@ -110,10 +105,6 @@ void CoreTiming::SyncPause(bool is_paused) {
if (!is_paused) { if (!is_paused) {
pause_end_time = GetGlobalTimeNs().count(); pause_end_time = GetGlobalTimeNs().count();
} }
for (auto& cb : pause_callbacks) {
cb(is_paused);
}
} }
bool CoreTiming::IsRunning() const { 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::optional<s64> CoreTiming::Advance() {
std::scoped_lock lock{advance_lock, basic_lock}; std::scoped_lock lock{advance_lock, basic_lock};
global_timer = GetGlobalTimeNs().count(); global_timer = GetGlobalTimeNs().count();

@ -22,7 +22,6 @@ namespace Core::Timing {
/// A callback that may be scheduled for a particular core timing event. /// A callback that may be scheduled for a particular core timing event.
using TimedCallback = std::function<std::optional<std::chrono::nanoseconds>( using TimedCallback = std::function<std::optional<std::chrono::nanoseconds>(
std::uintptr_t user_data, s64 time, std::chrono::nanoseconds ns_late)>; 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. /// Contains the characteristics of a particular event.
struct EventType { struct EventType {
@ -134,9 +133,6 @@ public:
/// Checks for events manually and returns time in nanoseconds for next event, threadsafe. /// Checks for events manually and returns time in nanoseconds for next event, threadsafe.
std::optional<s64> Advance(); std::optional<s64> Advance();
/// Register a callback function to be called when coretiming pauses.
void RegisterPauseCallback(PauseCallback&& callback);
private: private:
struct Event; struct Event;
@ -176,8 +172,6 @@ private:
/// Cycle timing /// Cycle timing
u64 ticks{}; u64 ticks{};
s64 downcount{}; s64 downcount{};
std::vector<PauseCallback> pause_callbacks{};
}; };
/// Creates a core timing event with the given name and callback. /// Creates a core timing event with the given name and callback.