Files
bigmak94andClaude Opus 5.5 b5f400bbbd AstroQuest 0.11: ASTRO BOT Rescue Mission in VR on Meta Quest 3 and PC VR
On top of the shadps4-arm64 core imported in the previous commit:

- PlayStation VR emulation: headset, tracker, reprojection, camera and social screen; the
  player's seat and view reset; head velocity for head-butts; field of view settings
- Sound: a native Ngs2 engine (samplers, submixers, effects), the Audio3d spatializer, virtual
  surround for headset speakers, microphone pass-through; libSceJson2; libSceFiber on FEX
- Fixes for CUSA12392 under emulation: real-time step, pace and resolution governor, larger
  render sizes on the PC, save loading at start
- Renderer: geometry shaders fed with fans/polygons/loops, cube-array layers of light probes,
  sample-count mismatches on Adreno, timeline semaphore hang, FXAA in place of the MSAA
  resolve, sharpening, VR frame export
- quest-host: the Quest app (OpenXR host that runs the glibc core as a child process, frames
  through AHardwareBuffers, DualSense mapping, hand-tracked controller placement, KGSL shim)
- PC: in-process OpenXR host (Virtual Desktop or any OpenXR runtime), Touch controllers as the
  gamepad, launcher with a settings window; vendored OpenXR SDK 1.1.63
- Builds keep the build machine's folders out of the binaries (-ffile-prefix-map); machine
  settings (Python, headset serial, signing key) live in git-ignored tools/*.local files
- tools: build, packaging and test scripts for Windows and the headset
- README with installation, license (GPL-2.0-or-later), third-party notices and thanks

No game files are part of the repository; .gitignore only lets listed paths in.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 15:00:43 +02:00

98 lines
3.8 KiB
C++

// Checks the head model and the 7.1 virtualizer with signals whose outcome is known:
// virtualizer_test prints level and delay between the ears for every speaker
// virtualizer_test in.wav out.wav renders an 8-channel 16-bit WAV to binaural stereo
#include <cmath>
#include <cstdio>
#include <cstring>
#include <random>
#include <vector>
#include "core/libraries/audio/surround_virtualizer.h"
using Libraries::AudioOut::SurroundVirtualizer;
static double Rms(const std::vector<float>& v, int offset) {
double sum = 0;
size_t n = 0;
for (size_t i = offset; i < v.size(); i += 2, ++n) sum += double(v[i]) * v[i];
return std::sqrt(sum / n);
}
/// Lag of the right ear behind the left one, in samples, by cross-correlation.
static int Lag(const std::vector<float>& v) {
const int frames = int(v.size() / 2);
double best = -1e30;
int best_lag = 0;
for (int lag = -48; lag <= 48; ++lag) {
double sum = 0;
for (int i = 64; i < frames - 64; ++i) sum += double(v[i * 2]) * v[(i + lag) * 2 + 1];
if (sum > best) {
best = sum;
best_lag = lag;
}
}
return best_lag;
}
int main(int argc, char** argv) {
const std::array<int, 8> layout = {0, 1, 2, 3, 4, 5, 6, 7};
if (argc == 3) {
std::FILE* in = std::fopen(argv[1], "rb");
std::FILE* out = std::fopen(argv[2], "wb");
if (!in || !out) return 1;
unsigned char header[44];
if (std::fread(header, 1, 44, in) != 44) return 1;
const unsigned short two = 2;
unsigned rate;
std::memcpy(&rate, header + 24, 4);
std::memcpy(header + 22, &two, 2);
const unsigned byte_rate = rate * 4;
const unsigned short align = 4;
std::memcpy(header + 28, &byte_rate, 4);
std::memcpy(header + 32, &align, 2);
std::fwrite(header, 1, 44, out);
SurroundVirtualizer virtualizer{layout, rate};
std::vector<short> block(256 * 8);
std::vector<float> stereo(256 * 2);
std::vector<short> pcm(256 * 2);
unsigned total = 0;
size_t got;
while ((got = std::fread(block.data(), 16, 256, in)) > 0) {
virtualizer.Process(block.data(), unsigned(got), stereo.data());
for (size_t i = 0; i < got * 2; ++i) {
float v = stereo[i] < -1 ? -1 : stereo[i] > 1 ? 1 : stereo[i];
pcm[i] = short(v * 32767);
}
std::fwrite(pcm.data(), 4, got, out);
total += unsigned(got) * 4;
}
const unsigned riff = total + 36;
std::fseek(out, 4, SEEK_SET);
std::fwrite(&riff, 4, 1, out);
std::fseek(out, 40, SEEK_SET);
std::fwrite(&total, 4, 1, out);
std::fclose(out);
return 0;
}
const char* names[8] = {"front left", "front right", "centre", "LFE",
"surround left", "surround right", "rear left", "rear right"};
std::mt19937 random{1234};
std::normal_distribution<float> noise{0.0f, 0.1f};
for (int channel = 0; channel < 8; ++channel) {
SurroundVirtualizer virtualizer{layout, 48000};
const unsigned frames = 48000;
std::vector<float> input(frames * 8, 0.0f), output(frames * 2);
for (unsigned i = 0; i < frames; ++i) input[i * 8 + channel] = noise(random);
for (unsigned at = 0; at < frames; at += 256) {
virtualizer.Process(input.data() + at * 8, std::min(256u, frames - at),
output.data() + at * 2);
}
const double left = Rms(output, 0), right = Rms(output, 1);
std::printf("%-14s left %6.1f dB right %6.1f dB (L-R %+5.1f dB) right lags by %+d samples\n",
names[channel], 20 * std::log10(left / 0.1), 20 * std::log10(right / 0.1),
20 * std::log10(left / right), Lag(output));
}
return 0;
}