mirror of
https://github.com/mihawk-99/PS5_RetroArch.git
synced 2026-10-18 23:09:29 -05:00
EmulationStation has sound: SDL2 with the PS5 fork's audio driver
ES-DE played nothing. PS5_OpenGL's SDL2 integration built SDL without
its audio subsystem, so ES-DE opened no device and logged "Failed to
create sample conversion stream". PS5_OpenGL 4eab7eb turns SDL's audio
on. The pinned fork's PS5 driver opens sceAudioOut on the main port for
the system user at 48 kHz, as this title's own output does. ES-DE is
linked against that SDL build (build/sdl2-retroarch-20261004-224929, made
with integration/SDL2/build.py native against this project's SDK).
frontends/es-de/ps5/capture_ps5.cpp now records, with each picture, the
sound driver SDL chose and how many of its devices are playing.
tools/run-title.sh prints both.
Evidence: evidence/esde-sound/ (capture.json, expectation.json).
Base PS5 13.40, build 716a3c05, run 231157:
ES-DE's log: "Audio driver: ps5", "Detected playback device: System
audio output device"; the conversion-stream errors are gone
pictures: at 4 s "sound ps5 (0 playing)", at 12 s, browsing with its
navigation sounds, "sound ps5 (1 playing)"
Hearing it on the TV is not part of a scripted run.
Command:
python3 ../PS5_OpenGL/integration/SDL2/build.py native \
--sdl-source .deps/ps5-sdl --sdk-prefix ../PS5_OpenGL/build/sdk/ps5-opengl-gl46 \
--payload-sdk .deps/native/ps5-payload-sdk \
--compiler-wrapper build/tools/prospero-clang18 --out ../PS5_OpenGL/build/sdl2-retroarch-<stamp>
(run from ../PS5_OpenGL, with the paths relative to it)
PS5_FRONTENDS='es-de picker' tools/build-title.sh
tools/run-title.sh --no-build --relaunch-test=1 --relaunch-image=es-de/es-de.bin \
--frontend-capture=4,12 --frontend-scroll --watch 35
Gates: tools/verify.sh PASS (format unit build integration evidence).
This commit is contained in:
1 parent
bf939c43c8
commit
2646f03cad
4 files changed
+72
-23
No files matched your search
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"step": "esde-sound",
|
||||
"recorded": "2026-10-05T03:20:21Z",
|
||||
"console_run": "base PS5 13.40, run 231157",
|
||||
"revision": "61b8ffe + PS5_OpenGL 4eab7eb",
|
||||
"command": "tools/run-title.sh --no-build --relaunch-test=1 --relaunch-image=es-de/es-de.bin --frontend-capture=4,12 --frontend-scroll --watch 35",
|
||||
"raw_capture": "klog/esde-sound/summary.txt",
|
||||
"raw_lines": 8,
|
||||
"raw_bytes": 708,
|
||||
"lines": [
|
||||
"==> tools/run-title.sh --no-build --relaunch-test=1 --relaunch-image=es-de/es-de.bin --frontend-capture=4,12 --frontend-scroll --watch 35 (base PS5 13.40, build 716a3c05, run 231157)",
|
||||
"SDL2: PS5_OpenGL 4eab7eb integration/SDL2 (SDL_AUDIO on: the fork's PS5 driver), build/sdl2-retroarch-20261004-224929; SDL_config.h: SDL_AUDIO_DRIVER_PS5 1",
|
||||
"es_log: Setting up AudioManager...",
|
||||
"es_log: Audio driver: ps5",
|
||||
"es_log: Detected playback device: System audio output device",
|
||||
"es_log: no 'Failed to create sample conversion stream' and no 'Unable to open audio device'",
|
||||
"process 277, frame 174 at 4 s: 1920x1080, GL error 0, sound ps5 (0 playing)",
|
||||
"process 277, frame 610 at 12 s: 1920x1080, GL error 0, sound ps5 (1 playing)"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"step": "esde-sound",
|
||||
"note": "EmulationStation has sound: SDL2 is built with the PS5 fork's audio driver (sceAudioOut, main port, 48 kHz), ES-DE opens it and its device plays while it browses.",
|
||||
"must_contain": [
|
||||
"es_log: Audio driver: ps5",
|
||||
"es_log: Detected playback device: System audio output device",
|
||||
"sound ps5 (1 playing)"
|
||||
],
|
||||
"must_not_contain": [],
|
||||
"human_check": "Hearing it: ES-DE's navigation sounds and video previews on the TV; not part of a scripted run."
|
||||
}
|
||||
@@ -12,7 +12,8 @@
|
||||
* the first, its back buffer is read and written as
|
||||
* /app0/es-de/capture-<run id>-<pid>-<seconds>.ppm (binary RGB, top row first), and a
|
||||
* line is added to /app0/es-de/capture-test.jsonl with the frame's number, size,
|
||||
* the OpenGL error state and the frame times since the line before: how far
|
||||
* the sound driver SDL chose and how many of its devices are playing, the OpenGL
|
||||
* error state and the frame times since the line before: how far
|
||||
* apart the swaps were and how long the swap itself took (it waits for the GPU
|
||||
* to finish the frame and for the flip). With "scroll", a Right key is pressed
|
||||
* every 400 ms from the fifth second on, as a person browsing the systems would,
|
||||
@@ -82,7 +83,8 @@ bool valid_run(const std::string &run)
|
||||
if (run.empty() || run.size() > 64)
|
||||
return false;
|
||||
for (char c : run)
|
||||
if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '-' || c == '_'))
|
||||
if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') ||
|
||||
c == '-' || c == '_'))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
@@ -101,7 +103,8 @@ void read_arm()
|
||||
state.scroll = fields == 3 && std::strstr(mode, "scroll") != nullptr;
|
||||
state.profile = fields == 3 && std::strstr(mode, "profile") != nullptr;
|
||||
state.quit = fields == 3 && std::strstr(mode, "quit") != nullptr;
|
||||
state.launch = fields == 3 && std::strstr(mode, "launch") != nullptr && !ps5_esde_started_from_game();
|
||||
state.launch =
|
||||
fields == 3 && std::strstr(mode, "launch") != nullptr && !ps5_esde_started_from_game();
|
||||
unsigned last = 0;
|
||||
for (char *token = std::strtok(list, ","); token; token = std::strtok(nullptr, ","))
|
||||
{
|
||||
@@ -175,7 +178,8 @@ void write_profile()
|
||||
for (unsigned index = 0; index < count; index++)
|
||||
{
|
||||
for (unsigned depth = 0; depth < sample_depth; depth++)
|
||||
std::fprintf(out, depth ? " %lx" : "%lx", static_cast<unsigned long>(samples[index][depth]));
|
||||
std::fprintf(out, depth ? " %lx" : "%lx",
|
||||
static_cast<unsigned long>(samples[index][depth]));
|
||||
std::fputc('\n', out);
|
||||
}
|
||||
std::fclose(out);
|
||||
@@ -199,23 +203,33 @@ float mean(const std::vector<float> &values)
|
||||
return values.empty() ? 0.0f : sum / float(values.size());
|
||||
}
|
||||
|
||||
void record(unsigned seconds, int width, int height, const std::string &file, unsigned error, bool written)
|
||||
void record(unsigned seconds, int width, int height, const std::string &file, unsigned error,
|
||||
bool written)
|
||||
{
|
||||
const auto &gaps = state.intervals_ms;
|
||||
const long slow = std::count_if(gaps.begin(), gaps.end(), [](float gap) { return gap > 25.0f; });
|
||||
const long slow =
|
||||
std::count_if(gaps.begin(), gaps.end(), [](float gap) { return gap > 25.0f; });
|
||||
/* Sound: the driver SDL chose and the devices playing now (ES-DE opens one). */
|
||||
const char *audio_driver = SDL_GetCurrentAudioDriver();
|
||||
int audio_playing = 0;
|
||||
for (SDL_AudioDeviceID device = 1; device <= 8; device++)
|
||||
audio_playing += SDL_GetAudioDeviceStatus(device) == SDL_AUDIO_PLAYING;
|
||||
if (std::FILE *out = std::fopen(record_file, "a"))
|
||||
{
|
||||
std::fprintf(out,
|
||||
"{\"run\":\"%s\",\"pid\":%d,\"seconds\":%u,\"frame\":%llu,\"width\":%d,\"height\":%d,"
|
||||
"\"file\":\"%s\",\"gl_error\":%u,\"written\":%s,\"interval_frames\":%zu,"
|
||||
"\"interval_ms\":{\"mean\":%.2f,\"p50\":%.2f,\"p95\":%.2f,\"max\":%.2f,\"over_25\":%ld},"
|
||||
"\"swap_ms\":{\"mean\":%.2f,\"p95\":%.2f,\"max\":%.2f},\"presses\":%u,\"slow\":[%s]}\n",
|
||||
state.run.c_str(), static_cast<int>(getpid()), seconds, state.frames, width, height,
|
||||
file.c_str(), error,
|
||||
written ? "true" : "false", gaps.size(), mean(gaps), percentile(gaps, 0.5f),
|
||||
percentile(gaps, 0.95f), percentile(gaps, 1.0f), slow, mean(state.swaps_ms),
|
||||
percentile(state.swaps_ms, 0.95f), percentile(state.swaps_ms, 1.0f), state.presses,
|
||||
state.slow.c_str());
|
||||
std::fprintf(
|
||||
out,
|
||||
"{\"run\":\"%s\",\"pid\":%d,\"seconds\":%u,\"frame\":%llu,\"width\":%d,\"height\":%d,"
|
||||
"\"audio_driver\":\"%s\",\"audio_playing\":%d,"
|
||||
"\"file\":\"%s\",\"gl_error\":%u,\"written\":%s,\"interval_frames\":%zu,"
|
||||
"\"interval_ms\":{\"mean\":%.2f,\"p50\":%.2f,\"p95\":%.2f,\"max\":%.2f,\"over_25\":%ld}"
|
||||
","
|
||||
"\"swap_ms\":{\"mean\":%.2f,\"p95\":%.2f,\"max\":%.2f},\"presses\":%u,\"slow\":[%s]}\n",
|
||||
state.run.c_str(), static_cast<int>(getpid()), seconds, state.frames, width, height,
|
||||
audio_driver ? audio_driver : "", audio_playing, file.c_str(), error,
|
||||
written ? "true" : "false", gaps.size(), mean(gaps), percentile(gaps, 0.5f),
|
||||
percentile(gaps, 0.95f), percentile(gaps, 1.0f), slow, mean(state.swaps_ms),
|
||||
percentile(state.swaps_ms, 0.95f), percentile(state.swaps_ms, 1.0f), state.presses,
|
||||
state.slow.c_str());
|
||||
std::fclose(out);
|
||||
}
|
||||
state.slow.clear();
|
||||
@@ -248,8 +262,8 @@ void capture(SDL_Window *window, unsigned seconds)
|
||||
{
|
||||
int width = 0, height = 0;
|
||||
SDL_GL_GetDrawableSize(window, &width, &height);
|
||||
const std::string file = "/app0/es-de/capture-" + state.run + "-" + std::to_string(getpid()) + "-" +
|
||||
std::to_string(seconds) + ".ppm";
|
||||
const std::string file = "/app0/es-de/capture-" + state.run + "-" + std::to_string(getpid()) +
|
||||
"-" + std::to_string(seconds) + ".ppm";
|
||||
if (width <= 0 || height <= 0 || width > 8192 || height > 8192)
|
||||
{
|
||||
record(seconds, width, height, file, 0, false);
|
||||
@@ -302,7 +316,8 @@ extern "C" void __wrap_SDL_GL_SwapWindow(SDL_Window *window)
|
||||
{
|
||||
char entry[64];
|
||||
std::snprintf(entry, sizeof(entry), "%s\"%.2f:%.0f@%u\"", state.slow.empty() ? "" : ",",
|
||||
std::chrono::duration<float>(now - state.first).count(), gap, state.presses_total);
|
||||
std::chrono::duration<float>(now - state.first).count(), gap,
|
||||
state.presses_total);
|
||||
state.slow += entry;
|
||||
}
|
||||
}
|
||||
@@ -314,7 +329,8 @@ extern "C" void __wrap_SDL_GL_SwapWindow(SDL_Window *window)
|
||||
press(SDL_SCANCODE_RETURN, SDLK_RETURN);
|
||||
state.launch_presses++;
|
||||
}
|
||||
if (state.scroll && state.next < state.seconds.size() && now - state.first >= std::chrono::seconds(5) &&
|
||||
if (state.scroll && state.next < state.seconds.size() &&
|
||||
now - state.first >= std::chrono::seconds(5) &&
|
||||
now - state.last_press >= std::chrono::milliseconds(400))
|
||||
{
|
||||
press_right();
|
||||
@@ -342,5 +358,6 @@ extern "C" void __wrap_SDL_GL_SwapWindow(SDL_Window *window)
|
||||
__real_SDL_GL_SwapWindow(window);
|
||||
if (!state.seconds.empty())
|
||||
state.swaps_ms.push_back(
|
||||
std::chrono::duration<float, std::milli>(std::chrono::steady_clock::now() - before).count());
|
||||
std::chrono::duration<float, std::milli>(std::chrono::steady_clock::now() - before)
|
||||
.count());
|
||||
}
|
||||
+2
-1
@@ -555,7 +555,8 @@ with connect(**dt.load_settings()) as ftp:
|
||||
pass
|
||||
print(f" {'process ' + str(row['pid']) + ', ' if 'pid' in row else ''}"
|
||||
f"frame {row['frame']} at {row['seconds']} s: {row['width']}x{row['height']}, "
|
||||
f"GL error {row['gl_error']}, {'saved to ' + str(local) if row['written'] else 'not written'}")
|
||||
f"GL error {row['gl_error']}, sound {row.get('audio_driver') or 'none'} "
|
||||
f"({row.get('audio_playing', 0)} playing), {'saved to ' + str(local) if row['written'] else 'not written'}")
|
||||
if "interval_ms" in row:
|
||||
gap, swap = row["interval_ms"], row["swap_ms"]
|
||||
print(f" {row['interval_frames']} frames before it ({row['presses']} presses): between swaps "
|
||||
|
||||
Reference in new issue
Block a user