Merge pull request #20534 from hrydgard/refactor-audio

Add internal AudioBackend interface
This commit is contained in:
Henrik Rydgård
2025-06-16 22:46:14 +02:00
committed by GitHub
32 changed files with 159 additions and 116 deletions
+3 -2
View File
@@ -842,6 +842,7 @@ add_library(Common STATIC
Common/Render/Text/draw_text_win.h
Common/Render/Text/draw_text_uwp.cpp
Common/Render/Text/draw_text_uwp.h
Common/Audio/AudioBackend.h
Common/System/Display.cpp
Common/System/Display.h
Common/System/System.h
@@ -2625,8 +2626,8 @@ add_dependencies(${CoreLibName} GitVersion)
set(WindowsFiles
Windows/WindowsAudio.cpp
Windows/WindowsAudio.h
Windows/WASAPIStream.cpp
Windows/WASAPIStream.h
Windows/WASAPIContext.cpp
Windows/WASAPIContext.h
Windows/Debugger/BreakpointWindow.cpp
Windows/Debugger/BreakpointWindow.h
Windows/Debugger/DumpMemoryWindow.cpp
+19
View File
@@ -0,0 +1,19 @@
#pragma once
#include <string>
#include <string_view>
#include <vector>
// Always 2 channels, 16-bit audio.
typedef int (*StreamCallback)(short *buffer, int numSamples, int rate, void *userdata);
// Note that the backend may override the passed in sample rate. The actual sample rate
// should be returned by SampleRate though.
class AudioBackend {
public:
virtual ~AudioBackend() {}
virtual bool Init(StreamCallback _callback, void *userdata = nullptr) = 0;
virtual int SampleRate() const = 0;
virtual int PeriodFrames() const = 0;
virtual void FrameUpdate() {}
};
+1
View File
@@ -361,6 +361,7 @@
<ClInclude Include="Arm64Emitter.h" />
<ClInclude Include="ArmCommon.h" />
<ClInclude Include="ArmEmitter.h" />
<ClInclude Include="Audio\AudioBackend.h" />
<ClInclude Include="BitScan.h" />
<ClInclude Include="BitSet.h" />
<ClInclude Include="Buffer.h" />
+6
View File
@@ -685,6 +685,9 @@
<ClInclude Include="..\ext\imgui\imgui_extras.h">
<Filter>ext\imgui</Filter>
</ClInclude>
<ClInclude Include="Audio\AudioBackend.h">
<Filter>Audio</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="ABI.cpp" />
@@ -1410,6 +1413,9 @@
<Filter Include="ext\sol">
<UniqueIdentifier>{ec7d8691-bb7f-4689-b66a-cb60c1f48afd}</UniqueIdentifier>
</Filter>
<Filter Include="Audio">
<UniqueIdentifier>{92746a51-33a9-4a00-af10-3538322f04f0}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<Text Include="..\ext\libpng17\CMakeLists.txt">
+3 -2
View File
@@ -164,16 +164,17 @@ LogManager::LogManager() {
stdioUseColor_ = isatty(fileno(stdout));
#endif
#if PPSSPP_PLATFORM(WINDOWS) && !PPSSPP_PLATFORM(UWP)
#if PPSSPP_PLATFORM(WINDOWS)
if (IsDebuggerPresent()) {
outputs_ |= LogOutput::DebugString;
}
#if !PPSSPP_PLATFORM(UWP)
if (!consoleLog_) {
consoleLog_ = new ConsoleListener();
}
outputs_ |= LogOutput::WinConsole;
#endif
#endif
}
LogManager::~LogManager() {
+3 -1
View File
@@ -15,6 +15,7 @@ struct KeyInput;
struct AxisInput;
class GraphicsContext;
class AudioBackend;
// The first function to get called, just write strings to the two pointers.
// This might get called multiple times in some implementations, you must be able to handle that.
@@ -64,7 +65,7 @@ void NativeFrame(GraphicsContext *graphicsContext);
// the rest of the game, so be careful with synchronization.
// Returns the number of samples actually output. The app should do everything it can
// to fill the buffer completely.
int NativeMix(short *audio, int num_samples, int sampleRateHz);
int NativeMix(short *audio, int num_samples, int sampleRateHz, void *userdata);
// Called when it's time to shutdown. After this has been called,
// no more calls to any other function will be made from the framework
@@ -92,3 +93,4 @@ bool Native_IsWindowHidden();
// TODO: Feels like this belongs elsewhere.
bool Native_UpdateScreenScale(int width, int height, float customScale);
AudioBackend *System_CreateAudioBackend();
-1
View File
@@ -771,7 +771,6 @@ static int DefaultAchievementVolume() {
static const ConfigSetting soundSettings[] = {
ConfigSetting("Enable", &g_Config.bEnableSound, true, CfgFlag::PER_GAME),
ConfigSetting("AudioBackend", &g_Config.iAudioBackend, 0, CfgFlag::PER_GAME),
ConfigSetting("ExtraAudioBuffering", &g_Config.bExtraAudioBuffering, false, CfgFlag::DEFAULT),
ConfigSetting("AudioBufferSize", &g_Config.iSDLAudioBufferSize, 256, CfgFlag::DEFAULT),
-1
View File
@@ -287,7 +287,6 @@ public:
// Sound
bool bEnableSound;
int iAudioBackend;
int iSDLAudioBufferSize;
// Legacy volume settings, 0-10. These get auto-upgraded and should not be used.
-6
View File
@@ -142,12 +142,6 @@ ENUM_CLASS_BITOPS(DisableHLEFlags);
std::string GPUBackendToString(GPUBackend backend);
GPUBackend GPUBackendFromString(std::string_view backend);
enum AudioBackendType {
AUDIO_BACKEND_AUTO,
AUDIO_BACKEND_DSOUND,
AUDIO_BACKEND_WASAPI,
};
// For iIOTimingMethod.
enum IOTimingMethods {
IOTIMING_FAST = 0,
+1 -1
View File
@@ -344,7 +344,7 @@ static u32 sceSasSetVoice(u32 core, int voiceNum, u32 vagAddr, int size, int loo
u32 prevVagAddr = v.vagAddr;
bool reset = false;
if (v.type != VOICETYPE_VAG || v.vagAddr != vagAddr || v.vagSize != size || v.loop != loop) {
if (v.type != VOICETYPE_VAG || v.vagAddr != vagAddr || v.vagSize != size || v.loop != (loop != 0)) {
v.type = VOICETYPE_VAG;
reset = true;
}
+7 -1
View File
@@ -33,6 +33,7 @@
#include "SDL_keyboard.h"
#endif
#include "Common/Audio/AudioBackend.h"
#include "Common/System/NativeApp.h"
#include "Common/System/Request.h"
#include "Common/GPU/OpenGL/GLFeatures.h"
@@ -78,7 +79,7 @@ SDL_AudioSpec g_retFmt;
static SDL_AudioDeviceID audioDev = 0;
extern void mixaudio(void *userdata, Uint8 *stream, int len) {
NativeMix((short *)stream, len / 4, AUDIO_FREQ);
NativeMix((short *)stream, len / 4, AUDIO_FREQ, userdata);
}
static void InitSDLAudioDevice() {
@@ -444,6 +445,11 @@ void System_LaunchUrl(LaunchUrlType urlType, const char *url)
QDesktopServices::openUrl(QUrl(url));
}
AudioBackend *System_CreateAudioBackend() {
// Use legacy mechanisms.
return nullptr;
}
static int mainInternal(QApplication &a) {
#ifdef MOBILE_DEVICE
emugl = new MainUI();
+7 -1
View File
@@ -34,6 +34,7 @@ SDLJoystick *joystick = NULL;
#include "Common/System/System.h"
#include "Common/System/Request.h"
#include "Common/System/NativeApp.h"
#include "Common/Audio/AudioBackend.h"
#include "ext/glslang/glslang/Public/ShaderLang.h"
#include "Common/Data/Format/PNGLoad.h"
#include "Common/Net/Resolve.h"
@@ -134,7 +135,7 @@ int getDisplayNumber(void) {
}
void sdl_mixaudio_callback(void *userdata, Uint8 *stream, int len) {
NativeMix((short *)stream, len / (2 * 2), g_sampleRate);
NativeMix((short *)stream, len / (2 * 2), g_sampleRate, userdata);
}
static SDL_AudioDeviceID audioDev = 0;
@@ -244,6 +245,11 @@ void System_Vibrate(int length_ms) {
// Ignore on PC
}
AudioBackend *System_CreateAudioBackend() {
// Use legacy mechanisms.
return nullptr;
}
static void InitializeFilters(std::vector<std::string> &filters, BrowseFileType type) {
switch (type) {
case BrowseFileType::BOOTABLE:
+1 -1
View File
@@ -7,7 +7,7 @@ StereoResampler g_resampler;
// numFrames is number of stereo frames.
// This is called from *outside* the emulator thread.
int NativeMix(int16_t *outStereo, int numFrames, int sampleRateHz) {
int NativeMix(int16_t *outStereo, int numFrames, int sampleRateHz, void *userdata) {
int validFrames = g_resampler.Mix(outStereo, numFrames, false, sampleRateHz);
// Mix sound effects on top.
+7 -1
View File
@@ -694,7 +694,13 @@ void GameSettingsScreen::CreateAudioSettings(UI::ViewGroup *audioSettings) {
});
#endif
if (sdlAudio || g_Config.iAudioBackend == AUDIO_BACKEND_WASAPI) {
#if PPSSPP_PLATFORM(WINDOWS) && !PPSSPP_PLATFORM(UWP)
const bool isWindows = true;
#else
const bool isWindows = false;
#endif
if (sdlAudio || isWindows) {
audioSettings->Add(new CheckBox(&g_Config.bAutoAudioDevice, a->T("Use new audio devices automatically")));
}
+17 -17
View File
@@ -86,6 +86,7 @@
#include "Common/GPU/ShaderTranslation.h"
#include "Common/VR/PPSSPPVR.h"
#include "Common/Thread/ThreadManager.h"
#include "Common/Audio/AudioBackend.h"
#include "Core/ControlMapper.h"
#include "Core/Config.h"
@@ -193,9 +194,7 @@ static int g_restartGraphics;
static bool g_windowHidden = false;
std::vector<std::function<void()>> g_pendingClosures;
#ifdef _WIN32
WindowsAudioBackend *winAudioBackend;
#endif
AudioBackend *g_audioBackend = nullptr;
std::thread *graphicsLoadThread;
@@ -839,14 +838,10 @@ bool NativeInitGraphics(GraphicsContext *graphicsContext) {
g_screenManager->setPostRenderCallback(&CallbackPostRender, nullptr);
g_screenManager->deviceRestored(g_draw);
#ifdef _WIN32
winAudioBackend = CreateAudioBackend((AudioBackendType)g_Config.iAudioBackend);
#if PPSSPP_PLATFORM(UWP)
winAudioBackend->Init(0, &NativeMix, 44100);
#else
winAudioBackend->Init(MainWindow::GetHWND(), &NativeMix, 44100);
#endif
#endif
g_audioBackend = System_CreateAudioBackend();
if (g_audioBackend) {
g_audioBackend->Init(&NativeMix);
}
#if defined(_WIN32) && !PPSSPP_PLATFORM(UWP)
if (IsWin7OrHigher()) {
@@ -932,11 +927,6 @@ void NativeShutdownGraphics() {
if (gpu)
gpu->DeviceLost();
#if PPSSPP_PLATFORM(WINDOWS)
delete winAudioBackend;
winAudioBackend = nullptr;
#endif
#if PPSSPP_PLATFORM(WINDOWS) && !PPSSPP_PLATFORM(UWP)
if (winCamera) {
winCamera->waitShutDown();
@@ -950,6 +940,11 @@ void NativeShutdownGraphics() {
}
#endif
if (g_audioBackend) {
delete g_audioBackend;
g_audioBackend = nullptr;
}
UIBackgroundShutdown();
delete g_gameInfoCache;
@@ -1097,6 +1092,10 @@ void NativeFrame(GraphicsContext *graphicsContext) {
g_screenManager->update();
if (g_audioBackend) {
g_audioBackend->FrameUpdate();
}
// Do this after g_screenManager.update() so we can receive setting changes before rendering.
{
std::vector<PendingMessage> toProcess;
@@ -1534,8 +1533,9 @@ void NativeShutdown() {
ShaderTranslationShutdown();
// Avoid shutting this down when restarting core.
if (!restarting)
if (!restarting) {
g_logManager.Shutdown();
}
g_threadManager.Teardown();
+4 -3
View File
@@ -11,6 +11,7 @@
#include "Common/GPU/thin3d_create.h"
#include "Common/Common.h"
#include "Common/Audio/AudioBackend.h"
#include "Common/Input/InputState.h"
#include "Common/File/VFS/VFS.h"
#include "Common/Thread/ThreadUtil.h"
@@ -51,8 +52,6 @@ using namespace Windows::ApplicationModel::DataTransfer;
using namespace Windows::Devices::Enumeration;
using namespace Concurrency;
// UGLY!
extern WindowsAudioBackend *winAudioBackend;
std::list<std::unique_ptr<InputDevice>> g_input;
// TODO: Use Microsoft::WRL::ComPtr<> for D3D11 objects?
@@ -362,10 +361,12 @@ std::vector<std::string> System_GetPropertyStringVec(SystemProperty prop) {
}
}
extern AudioBackend *g_audioBackend;
int64_t System_GetPropertyInt(SystemProperty prop) {
switch (prop) {
case SYSPROP_AUDIO_SAMPLE_RATE:
return winAudioBackend ? winAudioBackend->GetSampleRate() : -1;
return g_audioBackend ? g_audioBackend->SampleRate() : -1;
case SYSPROP_DEVICE_TYPE:
{
+14 -9
View File
@@ -7,19 +7,20 @@
#include "Common/Log.h"
#include "Common/Thread/ThreadUtil.h"
#include "Common/Audio/AudioBackend.h"
#include "XAudioSoundStream.h"
#include <process.h>
const size_t BUFSIZE = 32 * 1024;
class XAudioBackend : public WindowsAudioBackend {
class XAudioBackend : public AudioBackend {
public:
XAudioBackend();
~XAudioBackend() override;
bool Init(HWND window, StreamCallback callback, int sampleRate) override; // If fails, can safely delete the object
int GetSampleRate() const override { return sampleRate_; }
bool Init(StreamCallback callback, void *userdata = nullptr) override; // If fails, can safely delete the object
int SampleRate() const override { return sampleRate_; }
int PeriodFrames() const override { return 0; }
private:
bool RunSound();
@@ -32,7 +33,10 @@ private:
IXAudio2MasteringVoice *xaudioMaster = nullptr;
IXAudio2SourceVoice *xaudioVoice = nullptr;
int sampleRate_ = 0;
void *userdata_ = nullptr;
int sampleRate_ = 44100;
int periodFrames_ = 0;
char realtimeBuffer_[BUFSIZE]{};
uint32_t cursor_ = 0;
@@ -126,9 +130,9 @@ XAudioBackend::~XAudioBackend() {
xaudioDevice->Release();
}
bool XAudioBackend::Init(HWND window, StreamCallback _callback, int sampleRate) {
bool XAudioBackend::Init(StreamCallback _callback, void *userdata) {
callback_ = _callback;
sampleRate_ = sampleRate;
userdata_ = userdata;
return RunSound();
}
@@ -155,7 +159,7 @@ void XAudioBackend::PollLoop() {
// take ownership of the data. It needs to be big enough to fit the max number of buffers we check for
// above, which it is, easily.
int stereoSamplesRendered = (*callback_)((short*)&realtimeBuffer_[cursor_], readCount / 4, sampleRate_);
int stereoSamplesRendered = (*callback_)((short*)&realtimeBuffer_[cursor_], readCount / 4, sampleRate_, userdata_);
int numBytesRendered = 2 * sizeof(short) * stereoSamplesRendered;
XAUDIO2_BUFFER xaudioBuffer{};
@@ -170,12 +174,13 @@ void XAudioBackend::PollLoop() {
cursor_ = 0;
bytesLeftInBuffer = BUFSIZE;
}
periodFrames_ = stereoSamplesRendered;
}
SetEvent(exitEvent_);
}
WindowsAudioBackend *CreateAudioBackend(AudioBackendType type) {
AudioBackend *System_CreateAudioBackend() {
// Only one type available on UWP.
return new XAudioBackend();
}
-8
View File
@@ -1,9 +1 @@
#pragma once
#include "Common/CommonWindows.h"
#include "Core/Config.h"
#include "Windows/WindowsAudio.h"
// Factory
WindowsAudioBackend *CreateAudioBackend(AudioBackendType type);
+3 -3
View File
@@ -718,7 +718,7 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="W32Util\UAHMenuBar.cpp" />
<ClCompile Include="WASAPIStream.cpp" />
<ClCompile Include="WASAPIContext.cpp" />
<ClCompile Include="WindowsAudio.cpp" />
<ClCompile Include="WindowsHost.cpp" />
<ClCompile Include="main.cpp" />
@@ -1166,7 +1166,7 @@
<ClInclude Include="MainWindow.h" />
<ClInclude Include="GPU\WindowsGLContext.h" />
<ClInclude Include="W32Util\UAHMenuBar.h" />
<ClInclude Include="WASAPIStream.h" />
<ClInclude Include="WASAPIContext.h" />
<ClInclude Include="WindowsAudio.h" />
<ClInclude Include="WindowsHost.h" />
<ClInclude Include="main.h" />
@@ -1434,4 +1434,4 @@
<UserProperties RESOURCE_FILE="DaSh.rc" />
</VisualStudio>
</ProjectExtensions>
</Project>
</Project>
+2 -2
View File
@@ -181,7 +181,7 @@
<ClCompile Include="WindowsAudio.cpp">
<Filter>Windows\System</Filter>
</ClCompile>
<ClCompile Include="WASAPIStream.cpp">
<ClCompile Include="WASAPIContext.cpp">
<Filter>Windows\System</Filter>
</ClCompile>
<ClCompile Include="CaptureDevice.cpp">
@@ -390,7 +390,7 @@
<ClInclude Include="WindowsAudio.h">
<Filter>Windows\System</Filter>
</ClInclude>
<ClInclude Include="WASAPIStream.h">
<ClInclude Include="WASAPIContext.h">
<Filter>Windows\System</Filter>
</ClInclude>
<ClInclude Include="..\ppsspp_config.h" />
@@ -2,7 +2,7 @@
#include <initguid.h>
#include "WindowsAudio.h"
#include "WASAPIStream.h"
#include "WASAPIContext.h"
#include "Common/Log.h"
#include "Common/LogReporting.h"
#include "Core/Config.h"
@@ -186,8 +186,7 @@ private:
#define REFTIMES_PER_SEC (10000000/200)
#define REFTIMES_PER_MILLISEC (REFTIMES_PER_SEC / 1000)
WASAPIAudioBackend::WASAPIAudioBackend() : threadData_(0) {
}
WASAPIAudioBackend::WASAPIAudioBackend() : threadData_(0) { }
WASAPIAudioBackend::~WASAPIAudioBackend() {
if (threadData_ == 0) {
@@ -210,10 +209,10 @@ unsigned int WINAPI WASAPIAudioBackend::soundThread(void *param) {
return backend->RunThread();
}
bool WASAPIAudioBackend::Init(HWND window, StreamCallback callback, int sampleRate) {
bool WASAPIAudioBackend::Init(StreamCallback callback, void *userdata) {
threadData_ = 0;
userdata_ = userdata;
callback_ = callback;
sampleRate_ = sampleRate;
hThread_ = (HANDLE)_beginthreadex(0, 0, soundThread, (void *)this, 0, 0);
if (!hThread_)
return false;
@@ -493,7 +492,7 @@ void WASAPIAudioThread::Run() {
int chans = deviceFormat_->Format.nChannels;
switch (format_) {
case Format::IEEE_FLOAT:
callback_(shortBuf_, pNumAvFrames, sampleRate_);
callback_(shortBuf_, pNumAvFrames, sampleRate_, nullptr);
if (chans == 1) {
float *ptr = (float *)pData;
memset(ptr, 0, pNumAvFrames * chans * sizeof(float));
@@ -512,7 +511,7 @@ void WASAPIAudioThread::Run() {
}
break;
case Format::PCM16:
callback_((short *)pData, pNumAvFrames, sampleRate_);
callback_((short *)pData, pNumAvFrames, sampleRate_, nullptr);
break;
case Format::UNKNOWN:
break;
+28
View File
@@ -0,0 +1,28 @@
#pragma once
#include <atomic>
#include "WindowsAudio.h"
// This should only be included from WindowsAudio.cpp and WASAPIStream.cpp.
class WASAPIAudioBackend : public AudioBackend {
public:
WASAPIAudioBackend();
~WASAPIAudioBackend();
bool Init(StreamCallback callback, void *userdata) override; // If fails, can safely delete the object
int SampleRate() const override { return sampleRate_; }
int PeriodFrames() const override { return periodFrames_; } // amount of frames normally requested
void FrameUpdate() override {}
private:
int RunThread();
static unsigned int WINAPI soundThread(void *param);
HANDLE hThread_ = nullptr;
StreamCallback callback_ = nullptr;
int sampleRate_ = 0;
int periodFrames_ = 0;
void *userdata_ = 0;
std::atomic<int> threadData_{};
};
-24
View File
@@ -1,24 +0,0 @@
#pragma once
#include <atomic>
#include "WindowsAudio.h"
// This should only be included from WindowsAudio.cpp and WASAPIStream.cpp.
class WASAPIAudioBackend : public WindowsAudioBackend {
public:
WASAPIAudioBackend();
~WASAPIAudioBackend();
bool Init(HWND window, StreamCallback callback, int sampleRate) override; // If fails, can safely delete the object
int GetSampleRate() const override { return sampleRate_; }
private:
int RunThread();
static unsigned int WINAPI soundThread(void *param);
HANDLE hThread_ = nullptr;
StreamCallback callback_ = nullptr;
int sampleRate_ = 0;
std::atomic<int> threadData_;
};
+2 -2
View File
@@ -1,7 +1,7 @@
#include "Common/OSVersion.h"
#include "WindowsAudio.h"
#include "WASAPIStream.h"
#include "WASAPIContext.h"
WindowsAudioBackend *CreateAudioBackend(AudioBackendType type) {
AudioBackend *System_CreateAudioBackend() {
return new WASAPIAudioBackend();
}
+1 -15
View File
@@ -1,19 +1,5 @@
#pragma once
#include "Common/CommonWindows.h"
#include "Common/Audio/AudioBackend.h"
#include "Core/ConfigValues.h"
// Always 2 channels, 16-bit audio.
typedef int (*StreamCallback)(short *buffer, int numSamples, int rate);
// Note that the backend may override the passed in sample rate. The actual sample rate
// should be returned by GetSampleRate though.
class WindowsAudioBackend {
public:
virtual ~WindowsAudioBackend() {}
virtual bool Init(HWND window, StreamCallback _callback, int sampleRate) = 0;
virtual int GetSampleRate() const = 0;
};
// Factory
WindowsAudioBackend *CreateAudioBackend(AudioBackendType type);
+7 -2
View File
@@ -277,7 +277,7 @@ std::vector<std::string> System_GetPropertyStringVec(SystemProperty prop) {
}
// Ugly!
extern WindowsAudioBackend *winAudioBackend;
extern AudioBackend *winAudioBackend;
#ifdef _WIN32
#if PPSSPP_PLATFORM(UWP)
@@ -319,12 +319,16 @@ static float ScreenRefreshRateHz() {
return rate;
}
extern AudioBackend *g_audioBackend;
int64_t System_GetPropertyInt(SystemProperty prop) {
switch (prop) {
case SYSPROP_MAIN_WINDOW_HANDLE:
return (int64_t)MainWindow::GetHWND();
case SYSPROP_AUDIO_SAMPLE_RATE:
return winAudioBackend ? winAudioBackend->GetSampleRate() : -1;
return g_audioBackend ? g_audioBackend->SampleRate() : -1;
case SYSPROP_AUDIO_FRAMES_PER_BUFFER:
return g_audioBackend ? g_audioBackend->PeriodFrames() : -1;
case SYSPROP_DEVICE_TYPE:
return DEVICE_TYPE_DESKTOP;
case SYSPROP_DISPLAY_COUNT:
@@ -485,6 +489,7 @@ void System_Notify(SystemNotification notification) {
case SystemNotification::POLL_CONTROLLERS:
g_inputManager.PollControllers();
// Also poll the audio backend for changes.
break;
case SystemNotification::TOGGLE_DEBUG_CONSOLE:
+1 -1
View File
@@ -3,7 +3,7 @@
#include <string>
#include <mutex>
typedef int (*AndroidAudioCallback)(short *buffer, int numSamples, int sampleRateHz);
typedef int (*AndroidAudioCallback)(short *buffer, int numSamples, int sampleRateHz, void *userdata);
class AudioContext {
public:
+1 -1
View File
@@ -49,7 +49,7 @@ void OpenSLContext::BqPlayerCallback(SLAndroidSimpleBufferQueueItf bq) {
return;
}
int renderedFrames = audioCallback(buffer[curBuffer], framesPerBuffer, SampleRate());
int renderedFrames = audioCallback(buffer[curBuffer], framesPerBuffer, SampleRate(), nullptr);
int sizeInBytes = framesPerBuffer * 2 * sizeof(short);
int byteCount = (framesPerBuffer - renderedFrames) * 4;
+5
View File
@@ -820,6 +820,11 @@ retry:
}
}
AudioBackend *System_CreateAudioBackend() {
// Use legacy mechanisms.
return nullptr;
}
extern "C" void Java_org_ppsspp_ppsspp_NativeApp_audioInit(JNIEnv *, jclass) {
sampleRate = optimalSampleRate;
if (optimalSampleRate == 0) {
+2 -2
View File
@@ -19,7 +19,7 @@ static volatile BOOL done = 0;
#define SAMPLE_SIZE 44100
static short stream[SAMPLE_SIZE];
int NativeMix(short *audio, int numSamples, int sampleRateHz);
int NativeMix(short *audio, int numSamples, int sampleRateHz, void *userdata);
@interface AudioEngine ()
@@ -125,7 +125,7 @@ int NativeMix(short *audio, int numSamples, int sampleRateHz);
{
size_t frames_ready;
if (![self playing])
frames_ready = NativeMix(stream, SAMPLE_SIZE / 2, sampleRateHz);
frames_ready = NativeMix(stream, SAMPLE_SIZE / 2, sampleRateHz, 0);
else
frames_ready = 0;
+2 -2
View File
@@ -74,7 +74,7 @@ void iOSCoreAudioSetDisplayConnected(bool connected) {
iOSCoreAudioUpdateSession();
}
int NativeMix(short *audio, int numSamples, int sampleRate);
int NativeMix(short *audio, int numSamples, int sampleRate, void *userdata);
OSStatus iOSCoreAudioCallback(void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
@@ -85,7 +85,7 @@ OSStatus iOSCoreAudioCallback(void *inRefCon,
{
// see if we have any sound to play
short *output = (short *)ioData->mBuffers[0].mData;
UInt32 framesReady = NativeMix(output, inNumberFrames, SAMPLE_RATE);
UInt32 framesReady = NativeMix(output, inNumberFrames, SAMPLE_RATE, nullptr);
if (framesReady == 0) {
// oops, we don't currently have any sound, so return silence
+6
View File
@@ -28,6 +28,7 @@
#import "IAPManager.h"
#include "Common/MemoryUtil.h"
#include "Common/Audio/AudioBackend.h"
#include "Common/System/NativeApp.h"
#include "Common/System/System.h"
#include "Common/System/Request.h"
@@ -612,6 +613,11 @@ void System_Vibrate(int mode) {
}
}
AudioBackend *System_CreateAudioBackend() {
// Use legacy mechanisms.
return nullptr;
}
int main(int argc, char *argv[])
{
// SetCurrentThreadName("MainThread");