Move the resampler usage to a common file, AudioCommon. (#17176)

* Move the resampler usage to a common file, AudioCommon.

Ports that don't want to use the resampler can now simply exclude that
file and provide their own implementation. Next up, libretro will be
converted to do it that way.

* Android.mk typo

* libretro makefile fix

* libretro buildfix

* libretro: try a different approach for the temporary solution

* duh

* double duh
This commit is contained in:
Henrik Rydgård 2023-03-24 17:19:57 +01:00 committed by GitHub
parent b6b6066ee5
commit 349b73acec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 123 additions and 71 deletions

View File

@ -1293,6 +1293,13 @@ if(WIN32)
target_link_libraries(Common winmm d3d9 dsound)
endif()
if(NOT LIBRETRO)
list(APPEND NativeAppSource
UI/AudioCommon.h
UI/AudioCommon.cpp
)
endif()
list(APPEND NativeAppSource
android/jni/TestRunner.cpp
UI/DiscordIntegration.cpp

View File

@ -191,5 +191,17 @@ bool System_GetPropertyBool(SystemProperty prop);
void System_Notify(SystemNotification notification);
std::vector<std::string> System_GetCameraDeviceList();
bool System_AudioRecordingIsAvailable();
bool System_AudioRecordingState();
// For these functions, most platforms will use the implementation provided in UI/AudioCommon.cpp,
// no need to implement separately.
void System_AudioGetDebugStats(char *buf, size_t bufSize);
void System_AudioClear();
// These samples really have 16 bits of value, but can be a little out of range.
void System_AudioPushSamples(const int32_t *audio, int numSamples);
inline void System_AudioResetStatCounters() {
return System_AudioGetDebugStats(nullptr, 0);
}

View File

@ -23,6 +23,7 @@
#include "Common/Serialize/Serializer.h"
#include "Common/Serialize/SerializeFuncs.h"
#include "Common/Data/Collections/FixedSizeQueue.h"
#include "Common/System/System.h"
#ifdef _M_SSE
#include <emmintrin.h>
@ -44,38 +45,8 @@
#include "Core/HLE/sceAudio.h"
#include "Core/HLE/sceKernel.h"
#include "Core/HLE/sceKernelThread.h"
#include "Core/HW/StereoResampler.h"
#include "Core/Util/AudioFormat.h"
StereoResampler resampler;
// numFrames is number of stereo frames.
// This is called from *outside* the emulator thread.
int __AudioMix(short *outstereo, int numFrames, int sampleRate) {
return resampler.Mix(outstereo, numFrames, false, sampleRate);
}
void __AudioGetDebugStats(char *buf, size_t bufSize) {
resampler.GetAudioDebugStats(buf, bufSize);
}
void __AudioClear() {
resampler.Clear();
}
void __AudioPushSamples(const s32 *audio, int numSamples) {
if (audio) {
resampler.PushSamples(audio, numSamples);
} else {
resampler.Clear();
}
}
void __AudioResetStatCounters() {
resampler.ResetStatCounters();
}
// Should be used to lock anything related to the outAudioQueue.
// atomic locks are used on the lock. TODO: make this lock-free
std::atomic_flag atomicLock_;
@ -92,7 +63,6 @@ int srcFrequency = 0;
const int hwSampleRate = 44100;
const int hwBlockSize = 64;
const int hostAttemptBlockSize = 512;
static int audioIntervalCycles;
static int audioHostIntervalCycles;
@ -109,11 +79,6 @@ static bool m_logAudio;
static int chanQueueMaxSizeFactor;
static int chanQueueMinSizeFactor;
// Accessor for libretro
int __AudioGetHostAttemptBlockSize() {
return hostAttemptBlockSize;
}
static void hleAudioUpdate(u64 userdata, int cyclesLate) {
// Schedule the next cycle first. __AudioUpdate() may consume cycles.
CoreTiming::ScheduleEvent(audioIntervalCycles - cyclesLate, eventAudioUpdate, 0);
@ -131,12 +96,13 @@ static void hleHostAudioUpdate(u64 userdata, int cyclesLate) {
static void __AudioCPUMHzChange() {
audioIntervalCycles = (int)(usToCycles(1000000ULL) * hwBlockSize / hwSampleRate);
audioHostIntervalCycles = (int)(usToCycles(1000000ULL) * hostAttemptBlockSize / hwSampleRate);
// Soon to be removed.
audioHostIntervalCycles = (int)(usToCycles(1000000ULL) * 512 / hwSampleRate);
}
void __AudioInit() {
__AudioResetStatCounters();
System_AudioResetStatCounters();
mixFrequency = 44100;
srcFrequency = 0;
@ -159,7 +125,7 @@ void __AudioInit() {
clampedMixBuffer = new s16[hwBlockSize * 2];
memset(mixBuffer, 0, hwBlockSize * 2 * sizeof(s32));
__AudioClear();
System_AudioClear();
CoreTiming::RegisterMHzChangeCallback(&__AudioCPUMHzChange);
}
@ -184,16 +150,16 @@ void __AudioDoState(PointerWrap &p) {
if (s >= 2) {
// TODO: Next time we bump, get rid of this. It's kinda useless.
StereoResampler::DoState(p);
auto s = p.Section("resampler", 1);
if (p.mode == p.MODE_READ) {
__AudioClear();
System_AudioClear();
}
} else {
// Only to preserve the previous file format. Might cause a slight audio glitch on upgrades?
FixedSizeQueue<s16, 512 * 16> outAudioQueue;
outAudioQueue.DoState(p);
__AudioClear();
System_AudioClear();
}
int chanCount = ARRAY_SIZE(chans);
@ -455,7 +421,7 @@ void __AudioUpdate(bool resetRecording) {
}
if (g_Config.bEnableSound) {
__AudioPushSamples(mixBuffer, hwBlockSize);
System_AudioPushSamples(mixBuffer, hwBlockSize);
#ifndef MOBILE_DEVICE
if (g_Config.bSaveLoadResetsAVdumping && resetRecording) {
__StopLogAudio();

View File

@ -46,21 +46,11 @@ u32 __AudioEnqueue(AudioChannel &chan, int chanNum, bool blocking);
void __AudioWakeThreads(AudioChannel &chan, int result, int step);
void __AudioWakeThreads(AudioChannel &chan, int result);
// Resampler API, to be extracted
int __AudioMix(short *outstereo, int numSamples, int sampleRate);
void __AudioGetDebugStats(char *buf, size_t bufSize);
void __AudioClear();
void __AudioPushSamples(const s32 *audio, int numSamples); // Should not be used in-game, only at the menu!
void __AudioResetStatCounters();
int __AudioGetHostAttemptBlockSize();
// Audio Dumping stuff
void __StartLogAudio(const Path &filename);
void __StopLogAudio();
class WAVDump
{
class WAVDump {
public:
static void Reset();
};

View File

@ -343,7 +343,3 @@ void StereoResampler::ResetStatCounters() {
outputSampleCount_ = 0;
startTime_ = time_now_d();
}
void StereoResampler::DoState(PointerWrap &p) {
auto s = p.Section("resampler", 1);
}

View File

@ -22,7 +22,6 @@
#include <cstdint>
#include <atomic>
#include "Common/Serialize/Serializer.h"
#include "Common/CommonTypes.h"
struct AudioDebugStats;
@ -41,9 +40,6 @@ public:
void Clear();
// TODO: Get rid of this.
static void DoState(PointerWrap &p);
void GetAudioDebugStats(char *buf, size_t bufSize);
void ResetStatCounters();

31
UI/AudioCommon.cpp Normal file
View File

@ -0,0 +1,31 @@
#include "Common/System/System.h"
#include "Core/HW/StereoResampler.h" // TODO: doesn't belong in Core/HW...
#include "UI/AudioCommon.h"
StereoResampler g_resampler;
// numFrames is number of stereo frames.
// This is called from *outside* the emulator thread.
int __AudioMix(int16_t *outstereo, int numFrames, int sampleRate) {
return g_resampler.Mix(outstereo, numFrames, false, sampleRate);
}
void System_AudioGetDebugStats(char *buf, size_t bufSize) {
if (buf) {
g_resampler.GetAudioDebugStats(buf, bufSize);
} else {
g_resampler.ResetStatCounters();
}
}
void System_AudioClear() {
g_resampler.Clear();
}
void System_AudioPushSamples(const s32 *audio, int numSamples) {
if (audio) {
g_resampler.PushSamples(audio, numSamples);
} else {
g_resampler.Clear();
}
}

5
UI/AudioCommon.h Normal file
View File

@ -0,0 +1,5 @@
#pragma once
#include <cstdint>
int __AudioMix(int16_t *outstereo, int numFrames, int sampleRate);

View File

@ -7,6 +7,7 @@
#include "Common/CommonTypes.h"
#include "Common/Data/Format/RIFF.h"
#include "Common/Log.h"
#include "Common/System/System.h"
#include "Common/Serialize/SerializeFuncs.h"
#include "Common/TimeUtil.h"
#include "Common/Data/Collections/FixedSizeQueue.h"
@ -344,7 +345,7 @@ bool BackgroundAudio::Play() {
// Immediately stop the sound if it is turned off while playing.
if (!g_Config.bEnableSound) {
Clear(true);
__AudioClear();
System_AudioClear();
return true;
}
@ -393,7 +394,7 @@ bool BackgroundAudio::Play() {
}
}
__AudioPushSamples(buffer, sz);
System_AudioPushSamples(buffer, sz);
if (at3Reader_ && fadingOut_ && volume_ <= 0.0f) {
Clear(true);

View File

@ -1266,7 +1266,7 @@ Invalid / Unknown (%d)
static void DrawAudioDebugStats(UIContext *ctx, const Bounds &bounds) {
FontID ubuntu24("UBUNTU24");
char statbuf[4096] = { 0 };
__AudioGetDebugStats(statbuf, sizeof(statbuf));
System_AudioGetDebugStats(statbuf, sizeof(statbuf));
ctx->Flush();
ctx->BindFontTexture();

View File

@ -106,6 +106,7 @@
#include "Core/ThreadPools.h"
#include "GPU/GPUInterface.h"
#include "UI/AudioCommon.h"
#include "UI/BackgroundAudio.h"
#include "UI/ControlMappingScreen.h"
#include "UI/DiscordIntegration.h"

View File

@ -61,6 +61,7 @@
<ClCompile Include="ReportScreen.cpp" />
<ClCompile Include="SavedataScreen.cpp" />
<ClCompile Include="Store.cpp" />
<ClCompile Include="AudioCommon.cpp" />
<ClCompile Include="TiltAnalogSettingsScreen.cpp" />
<ClCompile Include="TouchControlLayoutScreen.cpp" />
<ClCompile Include="TouchControlVisibilityScreen.cpp" />
@ -68,6 +69,7 @@
<ClCompile Include="Theme.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="AudioCommon.h" />
<ClInclude Include="BackgroundAudio.h" />
<ClInclude Include="ChatScreen.h" />
<ClInclude Include="ComboKeyMappingScreen.h" />

View File

@ -82,6 +82,7 @@
<ClCompile Include="JoystickHistoryView.cpp">
<Filter>Views</Filter>
</ClCompile>
<ClCompile Include="AudioCommon.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="GameInfoCache.h" />
@ -165,6 +166,7 @@
<ClInclude Include="JoystickHistoryView.h">
<Filter>Views</Filter>
</ClInclude>
<ClInclude Include="AudioCommon.h" />
</ItemGroup>
<ItemGroup>
<Filter Include="Screens">

View File

@ -265,6 +265,7 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="..\..\UI\AudioCommon.h" />
<ClInclude Include="..\..\UI\BackgroundAudio.h" />
<ClInclude Include="..\..\UI\ChatScreen.h" />
<ClInclude Include="..\..\UI\ComboKeyMappingScreen.h" />
@ -300,6 +301,7 @@
<ClInclude Include="targetver.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\UI\AudioCommon.cpp" />
<ClCompile Include="..\..\UI\BackgroundAudio.cpp" />
<ClCompile Include="..\..\UI\ChatScreen.cpp" />
<ClCompile Include="..\..\UI\ComboKeyMappingScreen.cpp" />

View File

@ -33,6 +33,7 @@
<ClCompile Include="..\..\UI\ChatScreen.cpp" />
<ClCompile Include="..\..\UI\Theme.cpp" />
<ClCompile Include="..\..\UI\JoystickHistoryView.cpp" />
<ClCompile Include="..\..\UI\AudioCommon.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="pch.h" />
@ -68,5 +69,6 @@
<ClInclude Include="..\..\UI\ChatScreen.h" />
<ClInclude Include="..\..\UI\Theme.h" />
<ClInclude Include="..\..\UI\JoystickHistoryView.h" />
<ClInclude Include="..\..\UI\AudioCommon.h" />
</ItemGroup>
</Project>

View File

@ -715,6 +715,7 @@ LOCAL_SRC_FILES := \
$(SRC)/android/jni/AndroidVulkanContext.cpp \
$(SRC)/android/jni/AndroidAudio.cpp \
$(SRC)/android/jni/OpenSLContext.cpp \
$(SRC)/UI/AudioCommon.cpp \
$(SRC)/UI/BackgroundAudio.cpp \
$(SRC)/UI/DiscordIntegration.cpp \
$(SRC)/UI/ChatScreen.cpp \

View File

@ -119,6 +119,9 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string
void System_InputBoxGetString(const std::string &title, const std::string &defaultValue, std::function<void(bool, const std::string &)> cb) { cb(false, ""); }
void System_AskForPermission(SystemPermission permission) {}
PermissionStatus System_GetPermissionStatus(SystemPermission permission) { return PERMISSION_STATUS_GRANTED; }
void System_AudioGetDebugStats(char *buf, size_t bufSize) { if (buf) buf[0] = '\0'; }
void System_AudioClear() {}
void System_AudioPushSamples(const s32 *audio, int numSamples) {}
int printUsage(const char *progname, const char *reason)
{

View File

@ -32,6 +32,7 @@
#include "Core/HLE/sceUtility.h"
#include "Core/HLE/__sceAudio.h"
#include "Core/HW/MemoryStick.h"
#include "Core/HW/StereoResampler.h"
#include "Core/Host.h"
#include "Core/MemMap.h"
#include "Core/System.h"
@ -46,6 +47,8 @@
#include "GPU/Common/TextureScalerCommon.h"
#include "GPU/Common/PresentationCommon.h"
#include "UI/AudioCommon.h"
#include "libretro/libretro.h"
#include "libretro/LibretroGraphicsContext.h"
#include "libretro/libretro_core_options.h"
@ -388,11 +391,8 @@ class LibretroHost : public Host
LibretroHost() {}
void UpdateSound() override
{
int hostAttemptBlockSize = __AudioGetHostAttemptBlockSize();
const int blockSizeMax = 512;
static int16_t audio[blockSizeMax * 2];
assert(hostAttemptBlockSize <= blockSizeMax);
const int hostAttemptBlockSize = 512;
static int16_t audio[hostAttemptBlockSize * 2];
int samples = __AudioMix(audio, hostAttemptBlockSize, SAMPLERATE);
AudioBufferWrite(audio, samples);
}
@ -1881,6 +1881,38 @@ void NativeResized() {}
void System_Toast(const char *str) {}
// Temporary, to keep the old behavior before changing it.
StereoResampler g_resampler;
// numFrames is number of stereo frames.
// This is called from *outside* the emulator thread.
int __AudioMix(int16_t *outstereo, int numFrames, int sampleRate) {
return g_resampler.Mix(outstereo, numFrames, false, sampleRate);
}
void System_AudioGetDebugStats(char *buf, size_t bufSize) {
if (buf) {
g_resampler.GetAudioDebugStats(buf, bufSize);
} else {
g_resampler.ResetStatCounters();
}
}
void System_AudioClear() {
g_resampler.Clear();
}
void System_AudioPushSamples(const int32_t *audio, int numSamples) {
if (audio) {
g_resampler.PushSamples(audio, numSamples);
} else {
g_resampler.Clear();
}
}
#if PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(IOS)
std::vector<std::string> System_GetCameraDeviceList() { return std::vector<std::string>(); }
bool System_AudioRecordingIsAvailable() { return false; }

View File

@ -88,6 +88,9 @@ bool System_GetPropertyBool(SystemProperty prop) {
}
}
void System_Notify(SystemNotification notification) {}
void System_AudioGetDebugStats(char *buf, size_t bufSize) { if (buf) buf[0] = '\0'; }
void System_AudioClear() {}
void System_AudioPushSamples(const s32 *audio, int numSamples) {}
#if PPSSPP_PLATFORM(ANDROID)
JNIEnv *getEnv() {