Update to v095r08 release.

byuu says:

Changelog:
- added preliminary WASAPI driver (it's really terrible, though. Patches
  most welcome.)
- all of processor/ updated to auto fn() -> ret syntax
- all of gb/ updated to auto fn() -> ret syntax

If you want to test the WASAPI driver, then edit ui-tomoko/GNUmakefile,
and replace audio.xaudio2 with audio.wasapi Note that the two drivers
are incompatible and cannot co-exist (yet. We can probably make it work
in the future.)

All that's left for the auto fn() -> ret syntax is the NES core and the
balanced/performance SNES components. This is kind of a big deal because
this syntax change causes diffs between WIPs to go crazy. So the sooner
we get this done and out of the way, the better. It's also nice from
a consistency standpoint, of course.
This commit is contained in:
Tim Allen
2015-11-21 18:36:48 +11:00
parent 6adfe71836
commit a219f9c121
109 changed files with 2048 additions and 1951 deletions

View File

@@ -21,6 +21,7 @@ rubylink += $(if $(findstring audio.ao,$(ruby)),-lao)
rubylink += $(if $(findstring audio.directsound,$(ruby)),-ldsound)
rubylink += $(if $(findstring audio.pulseaudio,$(ruby)),-lpulse)
rubylink += $(if $(findstring audio.pulseaudiosimple,$(ruby)),-lpulse-simple)
rubylink += $(if $(findstring audio.wasapi,$(ruby)),-lavrt -luuid)
rubylink += $(if $(findstring audio.xaudio2,$(ruby)),-lole32)
rubylink += $(if $(findstring input.udev,$(ruby)),-ludev)

169
ruby/audio/wasapi.cpp Normal file
View File

@@ -0,0 +1,169 @@
#include <avrt.h>
#include <mmdeviceapi.h>
#include <audioclient.h>
#include <audiopolicy.h>
#include <devicetopology.h>
#include <endpointvolume.h>
#include <nall/dsp.hpp>
struct AudioWASAPI : Audio {
~AudioWASAPI() { term(); }
struct {
bool exclusive = false;
bool synchronize = false;
uint frequency = 44100;
} settings;
auto cap(const string& name) -> bool {
if(name == Audio::Exclusive) return true;
if(name == Audio::Synchronize) return true;
if(name == Audio::Frequency) return true;
return false;
}
auto get(const string& name) -> any {
if(name == Audio::Exclusive) return settings.exclusive;
if(name == Audio::Synchronize) return settings.synchronize;
if(name == Audio::Frequency) return settings.frequency;
return {};
}
auto set(const string& name, const any& value) -> bool {
if(name == Audio::Exclusive && value.get<bool>()) {
settings.exclusive = value.get<bool>();
return true;
}
if(name == Audio::Synchronize && value.is<bool>()) {
settings.synchronize = value.get<bool>();
return true;
}
if(name == Audio::Frequency && value.is<uint>()) {
settings.frequency = value.get<uint>();
dsp.setFrequency(settings.frequency);
return true;
}
return false;
}
auto sample(uint16 left, uint16 right) -> void {
int samples[] = {(int16)left, (int16)right};
dsp.sample(samples);
while(dsp.pending()) {
dsp.read(samples);
write(samples);
}
}
auto clear() -> void {
audioClient->Stop();
renderClient->GetBuffer(bufferFrameCount, &bufferData);
renderClient->ReleaseBuffer(bufferFrameCount, 0);
audioClient->Start();
}
auto init() -> bool {
if(CoCreateInstance(CLSID_MMDeviceEnumerator, nullptr, CLSCTX_ALL, IID_IMMDeviceEnumerator, (void**)&enumerator) != S_OK) return false;
if(enumerator->GetDefaultAudioEndpoint(eRender, eConsole, &device) != S_OK) return false;
if(device->Activate(IID_IAudioClient, CLSCTX_ALL, nullptr, (void**)&audioClient) != S_OK) return false;
if(settings.exclusive) {
if(device->OpenPropertyStore(STGM_READ, &propertyStore) != S_OK) return false;
if(propertyStore->GetValue(PKEY_AudioEngine_DeviceFormat, &propVariant) != S_OK) return false;
waveFormat = (WAVEFORMATEX*)propVariant.blob.pBlobData;
if(audioClient->GetDevicePeriod(nullptr, &devicePeriod) != S_OK) return false;
if(audioClient->Initialize(AUDCLNT_SHAREMODE_EXCLUSIVE, 0, devicePeriod, devicePeriod, waveFormat, nullptr) != S_OK) return false;
taskHandle = AvSetMmThreadCharacteristics(L"Pro Audio", &taskIndex);
} else {
if(audioClient->GetMixFormat(&waveFormat) != S_OK) return false;
if(audioClient->GetDevicePeriod(&devicePeriod, nullptr)) return false;
if(audioClient->Initialize(AUDCLNT_SHAREMODE_SHARED, 0, devicePeriod, 0, waveFormat, nullptr) != S_OK) return false;
}
if(audioClient->GetService(IID_IAudioRenderClient, (void**)&renderClient) != S_OK) return false;
if(audioClient->GetBufferSize(&bufferFrameCount) != S_OK) return false;
switch(((WAVEFORMATEXTENSIBLE*)waveFormat)->SubFormat.Data1) {
case 1: ieee = false; break; //fixed point
case 3: ieee = true; break; //floating point
default: return false; //unknown format; abort
}
dsp.setChannels(2);
dsp.setPrecision(16);
dsp.setFrequency(settings.frequency);
dsp.setResampler(DSP::ResampleEngine::Linear);
dsp.setResamplerFrequency(waveFormat->nSamplesPerSec);
dsp.setChannels(waveFormat->nChannels);
dsp.setPrecision(waveFormat->wBitsPerSample);
print("[WASAPI]\n");
print("Channels: ", waveFormat->nChannels, "\n");
print("Precision: ", waveFormat->wBitsPerSample, "\n");
print("Frequency: ", waveFormat->nSamplesPerSec, "\n");
print("IEEE-754: ", ieee, "\n");
print("Exclusive: ", settings.exclusive, "\n\n");
audioClient->Start();
return true;
}
auto term() -> void {
if(audioClient) {
audioClient->Stop();
}
if(taskHandle) {
AvRevertMmThreadCharacteristics(taskHandle);
taskHandle = nullptr;
}
}
private:
auto write(int samples[]) -> void {
while(true) {
uint32 padding = 0;
audioClient->GetCurrentPadding(&padding);
if(bufferFrameCount - padding < 1) {
if(!settings.synchronize) return;
continue;
}
break;
}
renderClient->GetBuffer(1, &bufferData);
if(ieee) {
auto buffer = (float*)bufferData;
buffer[0] = (int16)samples[0] / 32768.0;
buffer[1] = (int16)samples[1] / 32768.0;
} else {
auto buffer = (int16*)bufferData;
buffer[0] = (int16)samples[0];
buffer[1] = (int16)samples[1];
}
renderClient->ReleaseBuffer(1, 0);
}
DSP dsp;
IMMDeviceEnumerator* enumerator = nullptr;
IMMDevice* device = nullptr;
IPropertyStore* propertyStore = nullptr;
IAudioClient* audioClient = nullptr;
IAudioRenderClient* renderClient = nullptr;
WAVEFORMATEX* waveFormat = nullptr;
PROPVARIANT propVariant;
HANDLE taskHandle = nullptr;
DWORD taskIndex = 0;
REFERENCE_TIME devicePeriod = 0;
uint32 bufferFrameCount = 0;
uint8* bufferData = nullptr;
bool ieee = false;
};

View File

@@ -1,3 +1,8 @@
#ifdef _WIN32
#include <initguid.h>
#include <cguid.h>
#endif
#include <ruby/ruby.hpp>
using namespace nall;
using namespace ruby;
@@ -250,6 +255,10 @@ auto Video::availableDrivers() -> lstring {
#include <ruby/audio/pulseaudiosimple.cpp>
#endif
#if defined(AUDIO_WASAPI)
#include <ruby/audio/wasapi.cpp>
#endif
#if defined(AUDIO_XAUDIO2)
#include <ruby/audio/xaudio2.cpp>
#endif
@@ -257,6 +266,7 @@ auto Video::availableDrivers() -> lstring {
namespace ruby {
const string Audio::Device = "Device";
const string Audio::Exclusive = "Exclusive";
const string Audio::Handle = "Handle";
const string Audio::Synchronize = "Synchronize";
const string Audio::Frequency = "Frequency";
@@ -293,6 +303,10 @@ auto Audio::create(const string& driver) -> Audio* {
if(driver == "PulseAudioSimple") return new AudioPulseAudioSimple;
#endif
#if defined(AUDIO_WASAPI)
if(driver == "WASAPI") return new AudioWASAPI;
#endif
#if defined(AUDIO_XAUDIO2)
if(driver == "XAudio2") return new AudioXAudio2;
#endif
@@ -301,7 +315,9 @@ auto Audio::create(const string& driver) -> Audio* {
}
auto Audio::optimalDriver() -> string {
#if defined(AUDIO_XAUDIO2)
#if defined(AUDIO_WASAPI)
return "WASAPI";
#elif defined(AUDIO_XAUDIO2)
return "XAudio2";
#elif defined(AUDIO_DIRECTSOUND)
return "DirectSound";
@@ -325,6 +341,8 @@ auto Audio::optimalDriver() -> string {
auto Audio::safestDriver() -> string {
#if defined(AUDIO_DIRECTSOUND)
return "DirectSound";
#elif defined(AUDIO_WASAPI)
return "WASAPI";
#elif defined(AUDIO_XAUDIO2)
return "XAudio2";
#elif defined(AUDIO_ALSA)
@@ -347,6 +365,10 @@ auto Audio::safestDriver() -> string {
auto Audio::availableDrivers() -> lstring {
return {
#if defined(AUDIO_WASAPI)
"WASAPI",
#endif
#if defined(AUDIO_XAUDIO2)
"XAudio2",
#endif

View File

@@ -1,7 +1,7 @@
/* ruby
* author: byuu
* license: ISC
* version: 0.13 (2015-06-18)
* version: 0.14 (2015-11-19)
*
* ruby is a cross-platform hardware abstraction layer
* it provides a common interface to video, audio and input devices
@@ -46,6 +46,7 @@ struct Video {
struct Audio {
static const nall::string Device;
static const nall::string Exclusive;
static const nall::string Handle;
static const nall::string Synchronize;
static const nall::string Frequency;