2022-06-22 22:13:59 +00:00
|
|
|
#include "audio.h"
|
|
|
|
#include <Windows.h>
|
|
|
|
#include <xaudio2.h>
|
|
|
|
|
|
|
|
#define AUDIO_FREQUENCY 96000
|
|
|
|
static IXAudio2 *xaudio2 = NULL;
|
|
|
|
static IXAudio2MasteringVoice *master_voice = NULL;
|
|
|
|
static IXAudio2SourceVoice *source_voice = NULL;
|
|
|
|
static bool playing = false;
|
|
|
|
static GB_sample_t sample_pool[0x2000];
|
|
|
|
static unsigned pos = 0;
|
|
|
|
|
|
|
|
#define BATCH_SIZE 256
|
|
|
|
|
|
|
|
static const WAVEFORMATEX wave_format = {
|
|
|
|
.wFormatTag = WAVE_FORMAT_PCM,
|
|
|
|
.nChannels = 2,
|
|
|
|
.nSamplesPerSec = AUDIO_FREQUENCY,
|
|
|
|
.nAvgBytesPerSec = AUDIO_FREQUENCY * 4,
|
|
|
|
.nBlockAlign = 4,
|
|
|
|
.wBitsPerSample = 16,
|
|
|
|
.cbSize = 0
|
|
|
|
};
|
|
|
|
|
2022-06-24 11:18:53 +00:00
|
|
|
static bool _audio_is_playing(void)
|
2022-06-22 22:13:59 +00:00
|
|
|
{
|
|
|
|
return playing;
|
|
|
|
}
|
|
|
|
|
2022-06-24 11:18:53 +00:00
|
|
|
static void _audio_clear_queue(void)
|
|
|
|
{
|
|
|
|
pos = 0;
|
|
|
|
IXAudio2SourceVoice_FlushSourceBuffers(source_voice);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void _audio_set_paused(bool paused)
|
2022-06-22 22:13:59 +00:00
|
|
|
{
|
|
|
|
if (paused) {
|
|
|
|
playing = false;
|
|
|
|
IXAudio2SourceVoice_Stop(source_voice, 0, XAUDIO2_COMMIT_NOW);
|
2022-06-24 11:18:53 +00:00
|
|
|
_audio_clear_queue();
|
2022-06-22 22:13:59 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
playing = true;
|
|
|
|
IXAudio2SourceVoice_Start(source_voice, 0, XAUDIO2_COMMIT_NOW);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2022-06-24 11:18:53 +00:00
|
|
|
static unsigned _audio_get_frequency(void)
|
2022-06-22 22:13:59 +00:00
|
|
|
{
|
|
|
|
return AUDIO_FREQUENCY;
|
|
|
|
}
|
|
|
|
|
2022-06-24 11:18:53 +00:00
|
|
|
static size_t _audio_get_queue_length(void)
|
2022-06-22 22:13:59 +00:00
|
|
|
{
|
|
|
|
static XAUDIO2_VOICE_STATE state;
|
|
|
|
IXAudio2SourceVoice_GetState(source_voice, &state, XAUDIO2_VOICE_NOSAMPLESPLAYED);
|
|
|
|
|
|
|
|
return state.BuffersQueued * BATCH_SIZE + (pos & (BATCH_SIZE - 1));
|
|
|
|
}
|
|
|
|
|
2022-06-24 11:18:53 +00:00
|
|
|
static void _audio_queue_sample(GB_sample_t *sample)
|
2022-06-22 22:13:59 +00:00
|
|
|
{
|
|
|
|
if (!playing) return;
|
|
|
|
|
|
|
|
static XAUDIO2_BUFFER buffer = {.AudioBytes = sizeof(*sample) * BATCH_SIZE, };
|
|
|
|
sample_pool[pos] = *sample;
|
|
|
|
buffer.pAudioData = (void *)&sample_pool[pos & ~(BATCH_SIZE - 1)];
|
|
|
|
pos++;
|
|
|
|
pos &= 0x1fff;
|
|
|
|
if ((pos & (BATCH_SIZE - 1)) == 0) {
|
|
|
|
IXAudio2SourceVoice_SubmitSourceBuffer(source_voice, &buffer, NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-24 11:18:53 +00:00
|
|
|
static bool _audio_init(void)
|
2022-06-22 22:13:59 +00:00
|
|
|
{
|
|
|
|
HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
|
|
|
|
if (FAILED(hr)) {
|
|
|
|
fprintf(stderr, "CoInitializeEx failed: %lx\n", hr);
|
2022-06-24 11:18:53 +00:00
|
|
|
return false;
|
2022-06-22 22:13:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
hr = XAudio2Create(&xaudio2, 0, XAUDIO2_DEFAULT_PROCESSOR);
|
|
|
|
if (FAILED(hr)) {
|
|
|
|
fprintf(stderr, "XAudio2Create failed: %lx\n", hr);
|
2022-06-24 11:18:53 +00:00
|
|
|
return false;
|
2022-06-22 22:13:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
hr = IXAudio2_CreateMasteringVoice(xaudio2, &master_voice,
|
|
|
|
2, // 2 channels
|
|
|
|
AUDIO_FREQUENCY,
|
|
|
|
0, // Flags
|
|
|
|
0, // Device index
|
|
|
|
NULL, // Effect chain
|
|
|
|
AudioCategory_GameMedia // Category
|
|
|
|
);
|
|
|
|
if (FAILED(hr)) {
|
|
|
|
fprintf(stderr, "CreateMasteringVoice failed: %lx\n", hr);
|
2022-06-24 11:18:53 +00:00
|
|
|
return false;
|
2022-06-22 22:13:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
hr = IXAudio2_CreateSourceVoice(xaudio2, &source_voice, &wave_format, 0, XAUDIO2_DEFAULT_FREQ_RATIO, NULL, NULL, NULL);
|
|
|
|
|
|
|
|
if (FAILED(hr)) {
|
|
|
|
fprintf(stderr, "CreateSourceVoice failed: %lx\n", hr);
|
2022-06-24 11:18:53 +00:00
|
|
|
return false;
|
2022-06-22 22:13:59 +00:00
|
|
|
}
|
2022-06-24 11:18:53 +00:00
|
|
|
|
|
|
|
return true;
|
2022-06-22 22:13:59 +00:00
|
|
|
}
|
2022-06-24 11:18:53 +00:00
|
|
|
|
|
|
|
GB_AUDIO_DRIVER(XAudio2);
|