diff --git a/Core/HLE/__sceAudio.cpp b/Core/HLE/__sceAudio.cpp index 31573526ada1..1d311853480e 100644 --- a/Core/HLE/__sceAudio.cpp +++ b/Core/HLE/__sceAudio.cpp @@ -47,7 +47,6 @@ #include "Core/Util/AudioFormat.h" StereoResampler resampler; -AudioDebugStats g_AudioDebugStats; // Should be used to lock anything related to the outAudioQueue. // atomic locks are used on the lock. TODO: make this lock-free @@ -100,7 +99,7 @@ static void __AudioCPUMHzChange() { void __AudioInit() { - memset(&g_AudioDebugStats, 0, sizeof(g_AudioDebugStats)); + resampler.ResetStatCounters(); mixFrequency = 44100; srcFrequency = 0; @@ -459,9 +458,8 @@ int __AudioMix(short *outstereo, int numFrames, int sampleRate) { return resampler.Mix(outstereo, numFrames, false, sampleRate); } -const AudioDebugStats *__AudioGetDebugStats() { - resampler.GetAudioDebugStats(&g_AudioDebugStats); - return &g_AudioDebugStats; +void __AudioGetDebugStats(char *buf, size_t bufSize) { + resampler.GetAudioDebugStats(buf, bufSize); } void __PushExternalAudio(const s32 *audio, int numSamples) { diff --git a/Core/HLE/__sceAudio.h b/Core/HLE/__sceAudio.h index c836bd3f19cc..f6619ece7d4d 100644 --- a/Core/HLE/__sceAudio.h +++ b/Core/HLE/__sceAudio.h @@ -26,6 +26,7 @@ struct AudioDebugStats { int underrunCount; int overrunCount; int instantSampleRate; + int targetSampleRate; int lastPushSize; }; @@ -44,7 +45,7 @@ void __AudioWakeThreads(AudioChannel &chan, int result, int step); void __AudioWakeThreads(AudioChannel &chan, int result); int __AudioMix(short *outstereo, int numSamples, int sampleRate); -const AudioDebugStats *__AudioGetDebugStats(); +void __AudioGetDebugStats(char *buf, size_t bufSize); void __PushExternalAudio(const s32 *audio, int numSamples); // Should not be used in-game, only at the menu! // Audio Dumping stuff diff --git a/Core/HW/StereoResampler.cpp b/Core/HW/StereoResampler.cpp index 3894e6d771cb..cf049c5a1374 100644 --- a/Core/HW/StereoResampler.cpp +++ b/Core/HW/StereoResampler.cpp @@ -56,16 +56,7 @@ StereoResampler::StereoResampler() : m_bufsize(MAX_SAMPLES_DEFAULT) - , m_lowwatermark(LOW_WATERMARK_DEFAULT) - , m_input_sample_rate(44100) - , m_indexW(0) - , m_indexR(0) - , m_numLeftI(0.0f) - , m_frac(0) - , underrunCount_(0) - , overrunCount_(0) - , sample_rate_(0.0f) - , lastBufSize_(0) { + , m_lowwatermark(LOW_WATERMARK_DEFAULT) { // Need to have space for the worst case in case it changes. m_buffer = new int16_t[MAX_SAMPLES_EXTRA * 2](); @@ -75,7 +66,9 @@ StereoResampler::StereoResampler() // If framerate is "close"... if (refresh != 60.0f && refresh > 50.0f && refresh < 70.0f) { - SetInputSampleRate((int)(44100 * (refresh / 60.0f))); + int input_sample_rate = (int)(44100 * (refresh / 60.0f)); + ILOG("StereoResampler: Adjusting target sample rate to %dHz", input_sample_rate); + SetInputSampleRate(input_sample_rate); } UpdateBufferSize(); @@ -273,16 +266,32 @@ void StereoResampler::PushSamples(const s32 *samples, unsigned int num_samples) lastPushSize_ = num_samples; } -void StereoResampler::GetAudioDebugStats(AudioDebugStats *stats) { - stats->buffered = lastBufSize_; - stats->underrunCount += underrunCount_; +void StereoResampler::GetAudioDebugStats(char *buf, size_t bufSize) { + snprintf(buf, bufSize, + "Audio buffer: %d/%d (low watermark: %d)\n" + "Underruns: %d\n" + "Overruns: %d\n" + "Sample rate: %d (input: %d)\n" + "Push size: %d\n", + lastBufSize_, + m_bufsize * 2, + m_lowwatermark, + underrunCountTotal_, + overrunCountTotal_, + (int)sample_rate_, + m_input_sample_rate, + lastPushSize_); + underrunCountTotal_ += underrunCount_; + overrunCountTotal_ += overrunCount_; underrunCount_ = 0; - stats->overrunCount += overrunCount_; overrunCount_ = 0; - stats->watermark = m_lowwatermark; - stats->bufsize = m_bufsize * 2; - stats->instantSampleRate = (int)sample_rate_; - stats->lastPushSize = lastPushSize_; +} + +void StereoResampler::ResetStatCounters() { + underrunCount_ = 0; + overrunCount_ = 0; + underrunCountTotal_ = 0; + overrunCountTotal_ = 0; } void StereoResampler::SetInputSampleRate(unsigned int rate) { diff --git a/Core/HW/StereoResampler.h b/Core/HW/StereoResampler.h index 57dbe37773bf..64fd3743025a 100644 --- a/Core/HW/StereoResampler.h +++ b/Core/HW/StereoResampler.h @@ -42,7 +42,8 @@ class StereoResampler { void DoState(PointerWrap &p); - void GetAudioDebugStats(AudioDebugStats *stats); + void GetAudioDebugStats(char *buf, size_t bufSize); + void ResetStatCounters(); protected: void UpdateBufferSize(); @@ -50,15 +51,17 @@ class StereoResampler { int m_bufsize; int m_lowwatermark; - unsigned int m_input_sample_rate; + unsigned int m_input_sample_rate = 44100; int16_t *m_buffer; - volatile u32 m_indexW; - volatile u32 m_indexR; - float m_numLeftI; - u32 m_frac; - int underrunCount_; - int overrunCount_; - float sample_rate_; - int lastBufSize_; - int lastPushSize_; + volatile u32 m_indexW = 0; + volatile u32 m_indexR = 0; + float m_numLeftI = 0.0f; + u32 m_frac = 0; + int underrunCount_ = 0; + int overrunCount_ = 0; + int underrunCountTotal_ = 0; + int overrunCountTotal_ = 0; + float sample_rate_ = 0.0; + int lastBufSize_ = 0; + int lastPushSize_ = 0; }; diff --git a/SDL/SDLMain.cpp b/SDL/SDLMain.cpp index 82651123ea0b..087478a08193 100644 --- a/SDL/SDLMain.cpp +++ b/SDL/SDLMain.cpp @@ -68,6 +68,8 @@ static int g_DesktopWidth = 0; static int g_DesktopHeight = 0; static float g_RefreshRate = 60.f; +static SDL_AudioSpec g_retFmt; + int getDisplayNumber(void) { int displayNumber = 0; char * displayNumberStr; @@ -90,7 +92,7 @@ static SDL_AudioDeviceID audioDev = 0; // Must be called after NativeInit(). static void InitSDLAudioDevice(const std::string &name = "") { - SDL_AudioSpec fmt, ret_fmt; + SDL_AudioSpec fmt; memset(&fmt, 0, sizeof(fmt)); fmt.freq = 44100; fmt.format = AUDIO_S16; @@ -106,24 +108,25 @@ static void InitSDLAudioDevice(const std::string &name = "") { audioDev = 0; if (!startDevice.empty()) { - audioDev = SDL_OpenAudioDevice(startDevice.c_str(), 0, &fmt, &ret_fmt, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE); + audioDev = SDL_OpenAudioDevice(startDevice.c_str(), 0, &fmt, &g_retFmt, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE); if (audioDev <= 0) { WLOG("Failed to open audio device: %s", startDevice.c_str()); } } if (audioDev <= 0) { - audioDev = SDL_OpenAudioDevice(nullptr, 0, &fmt, &ret_fmt, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE); + ILOG("SDL: Trying a different device"); + audioDev = SDL_OpenAudioDevice(nullptr, 0, &fmt, &g_retFmt, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE); } if (audioDev <= 0) { ELOG("Failed to open audio: %s", SDL_GetError()); } else { - if (ret_fmt.samples != fmt.samples) // Notify, but still use it - ELOG("Output audio samples: %d (requested: %d)", ret_fmt.samples, fmt.samples); - if (ret_fmt.freq != fmt.freq || ret_fmt.format != fmt.format || ret_fmt.channels != fmt.channels) { + if (g_retFmt.samples != fmt.samples) // Notify, but still use it + ELOG("Output audio samples: %d (requested: %d)", g_retFmt.samples, fmt.samples); + if (g_retFmt.freq != fmt.freq || g_retFmt.format != fmt.format || g_retFmt.channels != fmt.channels) { ELOG("Sound buffer format does not match requested format."); - ELOG("Output audio freq: %d (requested: %d)", ret_fmt.freq, fmt.freq); - ELOG("Output audio format: %d (requested: %d)", ret_fmt.format, fmt.format); - ELOG("Output audio channels: %d (requested: %d)", ret_fmt.channels, fmt.channels); + ELOG("Output audio freq: %d (requested: %d)", g_retFmt.freq, fmt.freq); + ELOG("Output audio format: %d (requested: %d)", g_retFmt.format, fmt.format); + ELOG("Output audio channels: %d (requested: %d)", g_retFmt.channels, fmt.channels); ELOG("Provided output format does not match requirement, turning audio off"); SDL_CloseAudioDevice(audioDev); } @@ -319,7 +322,9 @@ std::string System_GetProperty(SystemProperty prop) { int System_GetPropertyInt(SystemProperty prop) { switch (prop) { case SYSPROP_AUDIO_SAMPLE_RATE: - return 44100; + return g_retFmt.freq; + case SYSPROP_AUDIO_FRAMES_PER_BUFFER: + return g_retFmt.samples; case SYSPROP_DEVICE_TYPE: #if defined(MOBILE_DEVICE) return DEVICE_TYPE_MOBILE; diff --git a/UI/DevScreens.cpp b/UI/DevScreens.cpp index e39888d0414b..f146d099e9da 100644 --- a/UI/DevScreens.cpp +++ b/UI/DevScreens.cpp @@ -502,7 +502,7 @@ void SystemInfoScreen::CreateViews() { deviceSpecs->Add(new ItemHeader(si->T("OS Information"))); deviceSpecs->Add(new InfoItem(si->T("Memory Page Size"), StringFromFormat(si->T("%d bytes"), GetMemoryProtectPageSize()))); deviceSpecs->Add(new InfoItem(si->T("RW/RX exclusive"), PlatformIsWXExclusive() ? di->T("Active") : di->T("Inactive"))); -#ifdef ANDROID +#if PPSSPP_PLATFORM(ANDROID) deviceSpecs->Add(new InfoItem(si->T("Sustained perf mode"), System_GetPropertyBool(SYSPROP_SUPPORTS_SUSTAINED_PERF_MODE) ? di->T("Supported") : di->T("Unsupported"))); #endif @@ -512,14 +512,19 @@ void SystemInfoScreen::CreateViews() { #endif deviceSpecs->Add(new InfoItem(si->T("PPSSPP build"), build)); -#ifdef __ANDROID__ deviceSpecs->Add(new ItemHeader(si->T("Audio Information"))); deviceSpecs->Add(new InfoItem(si->T("Sample rate"), StringFromFormat("%d Hz", System_GetPropertyInt(SYSPROP_AUDIO_SAMPLE_RATE)))); - deviceSpecs->Add(new InfoItem(si->T("Frames per buffer"), StringFromFormat("%d", System_GetPropertyInt(SYSPROP_AUDIO_FRAMES_PER_BUFFER)))); + int framesPerBuffer = System_GetPropertyInt(SYSPROP_AUDIO_FRAMES_PER_BUFFER); + if (framesPerBuffer > 0) { + deviceSpecs->Add(new InfoItem(si->T("Frames per buffer"), StringFromFormat("%d", framesPerBuffer))); + } +#if PPSSPP_PLATFORM(ANDROID) deviceSpecs->Add(new InfoItem(si->T("Optimal sample rate"), StringFromFormat("%d Hz", System_GetPropertyInt(SYSPROP_AUDIO_OPTIMAL_SAMPLE_RATE)))); deviceSpecs->Add(new InfoItem(si->T("Optimal frames per buffer"), StringFromFormat("%d", System_GetPropertyInt(SYSPROP_AUDIO_OPTIMAL_FRAMES_PER_BUFFER)))); +#endif deviceSpecs->Add(new ItemHeader(si->T("Display Information"))); +#if PPSSPP_PLATFORM(ANDROID) deviceSpecs->Add(new InfoItem(si->T("Native Resolution"), StringFromFormat("%dx%d", System_GetPropertyInt(SYSPROP_DISPLAY_XRES), System_GetPropertyInt(SYSPROP_DISPLAY_YRES)))); diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index d3fd56050d4b..d32353f71d50 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -1265,19 +1265,8 @@ static void DrawDebugStats(DrawBuffer *draw2d, const Bounds &bounds) { static void DrawAudioDebugStats(DrawBuffer *draw2d, const Bounds &bounds) { FontID ubuntu24("UBUNTU24"); - char statbuf[1024] = { 0 }; - const AudioDebugStats *stats = __AudioGetDebugStats(); - snprintf(statbuf, sizeof(statbuf), - "Audio buffer: %d/%d (low watermark: %d)\n" - "Underruns: %d\n" - "Overruns: %d\n" - "Sample rate: %d\n" - "Push size: %d\n", - stats->buffered, stats->bufsize, stats->watermark, - stats->underrunCount, - stats->overrunCount, - stats->instantSampleRate, - stats->lastPushSize); + char statbuf[4096] = { 0 }; + __AudioGetDebugStats(statbuf, sizeof(statbuf)); draw2d->SetFontScale(0.7f, 0.7f); draw2d->DrawTextRect(ubuntu24, statbuf, bounds.x + 11, bounds.y + 31, bounds.w - 20, bounds.h - 30, 0xc0000000, FLAG_DYNAMIC_ASCII | FLAG_WRAP_TEXT); draw2d->DrawTextRect(ubuntu24, statbuf, bounds.x + 10, bounds.y + 30, bounds.w - 20, bounds.h - 30, 0xFFFFFFFF, FLAG_DYNAMIC_ASCII | FLAG_WRAP_TEXT);