55 lines
1.8 KiB
C++
55 lines
1.8 KiB
C++
#pragma once
|
|
|
|
#include <atomic>
|
|
#include <optional>
|
|
#include <thread>
|
|
#include <vector>
|
|
|
|
#include <audioclient.h>
|
|
|
|
#include "hooks/audio/implementations/backend.h"
|
|
|
|
// discards all audio while pacing the game's event handle once per buffer period, so the game
|
|
// keeps running normally with nothing output to any real device. routed through the shared
|
|
// DummyIAudioClient, the same plumbing the asio backend uses.
|
|
struct NullDiscardBackend final : AudioBackend {
|
|
~NullDiscardBackend() final;
|
|
|
|
const WAVEFORMATEXTENSIBLE &format() const noexcept override;
|
|
|
|
HRESULT on_initialize(
|
|
AUDCLNT_SHAREMODE *,
|
|
DWORD *,
|
|
REFERENCE_TIME *hnsBufferDuration,
|
|
REFERENCE_TIME *,
|
|
const WAVEFORMATEX *pFormat,
|
|
LPCGUID) override;
|
|
HRESULT on_get_buffer_size(uint32_t *buffer_frames) override;
|
|
HRESULT on_get_stream_latency(REFERENCE_TIME *latency) override;
|
|
HRESULT on_get_current_padding(std::optional<uint32_t> &padding_frames) override;
|
|
HRESULT on_is_format_supported(
|
|
AUDCLNT_SHAREMODE *,
|
|
const WAVEFORMATEX *,
|
|
WAVEFORMATEX **ppClosestMatch) override;
|
|
HRESULT on_get_mix_format(WAVEFORMATEX **) override;
|
|
HRESULT on_get_device_period(
|
|
REFERENCE_TIME *default_device_period,
|
|
REFERENCE_TIME *minimum_device_period) override;
|
|
HRESULT on_start() override;
|
|
HRESULT on_stop() override;
|
|
HRESULT on_set_event_handle(HANDLE *event_handle) override;
|
|
HRESULT on_get_buffer(uint32_t num_frames_requested, BYTE **ppData) override;
|
|
HRESULT on_release_buffer(uint32_t, DWORD) override;
|
|
|
|
private:
|
|
void pace_loop();
|
|
|
|
WAVEFORMATEXTENSIBLE format_ {};
|
|
uint32_t buffer_frames = 0;
|
|
REFERENCE_TIME period_reftime = 0;
|
|
HANDLE relay_handle = nullptr;
|
|
std::vector<BYTE> scratch;
|
|
std::thread pacing_thread;
|
|
std::atomic<bool> running = false;
|
|
};
|