mirror of
https://github.com/bsnes-emu/bsnes.git
synced 2025-08-20 22:31:20 +02:00
Update to v103r14 release.
byuu says: Changelog: - tomoko: by popular choice, default to adaptive mode on new installs - hiro/windows: fix bug that was preventing the escape key from closing some dialog windows - nall/registry: use "\\\\" as separator instead of "/" ... because some registry keys contain "/" in them >_> - ruby: add ASIO driver stub (so far it can only initialize and grab the driver name/version information)
This commit is contained in:
90
ruby/audio/asio.cpp
Normal file
90
ruby/audio/asio.cpp
Normal file
@@ -0,0 +1,90 @@
|
||||
#include "asio.hpp"
|
||||
|
||||
struct AudioASIO : Audio {
|
||||
~AudioASIO() { term(); }
|
||||
|
||||
struct Settings {
|
||||
HWND handle = nullptr;
|
||||
bool synchronize = true;
|
||||
uint frequency = 48000;
|
||||
} settings;
|
||||
|
||||
struct Driver {
|
||||
string name;
|
||||
string classID;
|
||||
};
|
||||
vector<Driver> drivers;
|
||||
|
||||
Driver driver;
|
||||
IASIO* device = nullptr;
|
||||
|
||||
auto cap(const string& name) -> bool {
|
||||
if(name == Audio::Handle) 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::Handle) return (uintptr)settings.handle;
|
||||
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::Handle && value.is<uintptr>()) {
|
||||
settings.handle = (HWND)value.get<uintptr>();
|
||||
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>();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
auto sample(int16_t left, int16_t right) -> void {
|
||||
}
|
||||
|
||||
auto clear() -> void {
|
||||
}
|
||||
|
||||
auto init() -> bool {
|
||||
//enumerate available ASIO drivers from the registry
|
||||
for(auto candidate : registry::contents("HKLM\\SOFTWARE\\ASIO\\")) {
|
||||
if(auto classID = registry::read({"HKLM\\SOFTWARE\\ASIO\\", candidate, "CLSID"})) {
|
||||
drivers.append({candidate.trimRight("\\", 1L), classID});
|
||||
}
|
||||
}
|
||||
if(!drivers) return false;
|
||||
|
||||
//default to first driver for now
|
||||
driver = drivers[0];
|
||||
|
||||
CLSID classID;
|
||||
if(CLSIDFromString((LPOLESTR)utf16_t(driver.classID), (LPCLSID)&classID) != S_OK) return false;
|
||||
if(CoCreateInstance(classID, 0, CLSCTX_INPROC_SERVER, classID, (void**)&device) != S_OK) return false;
|
||||
|
||||
if(!device->init((void*)settings.handle)) return false;
|
||||
|
||||
//temporary debugging information
|
||||
char driverName[4096] = {0};
|
||||
device->getDriverName(driverName);
|
||||
print("Driver: ", driverName, "\n");
|
||||
print("Version: ", device->getDriverVersion(), "\n");
|
||||
print("---\n");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
auto term() -> void {
|
||||
}
|
||||
};
|
171
ruby/audio/asio.hpp
Normal file
171
ruby/audio/asio.hpp
Normal file
@@ -0,0 +1,171 @@
|
||||
using ASIOError = long;
|
||||
enum : long {
|
||||
ASE_OK = 0,
|
||||
ASE_SUCCESS = 0x3f4847a0,
|
||||
ASE_NotPresent = -1000,
|
||||
ASE_HWMalfunction,
|
||||
ASE_InvalidParameter,
|
||||
ASE_InvalidMode,
|
||||
ASE_SPNotAdvancing,
|
||||
ASE_NoClock,
|
||||
ASE_NoMemory,
|
||||
};
|
||||
|
||||
using ASIOBool = long;
|
||||
enum : long {
|
||||
ASIOFalse = 0,
|
||||
ASIOTrue = 1,
|
||||
};
|
||||
|
||||
using ASIOSampleRate = double;
|
||||
using ASIOSamples = long long int;
|
||||
using ASIOTimeStamp = long long int;
|
||||
|
||||
using ASIOSampleType = long;
|
||||
enum : long {
|
||||
ASIOSTInt16MSB = 0,
|
||||
ASIOSTInt24MSB = 1,
|
||||
ASIOSTInt32MSB = 2,
|
||||
ASIOSTFloat32MSB = 3,
|
||||
ASIOSTFloat64MSB = 4,
|
||||
|
||||
ASIOSTInt32MSB16 = 8,
|
||||
ASIOSTInt32MSB18 = 9,
|
||||
ASIOSTInt32MSB20 = 10,
|
||||
ASIOSTInt32MSB24 = 11,
|
||||
|
||||
ASIOSTInt16LSB = 16,
|
||||
ASIOSTInt24LSB = 17,
|
||||
ASIOSTInt32LSB = 18,
|
||||
ASIOSTFloat32LSB = 19,
|
||||
ASIOSTFloat64LSB = 20,
|
||||
|
||||
ASIOSTInt32LSB16 = 24,
|
||||
ASIOSTInt32LSB18 = 25,
|
||||
ASIOSTInt32LSB20 = 26,
|
||||
ASIOSTInt32LSB24 = 27,
|
||||
|
||||
ASIOSTDSDInt8LSB1 = 32,
|
||||
ASIOSTDSDInt8MSB1 = 33,
|
||||
ASIOSTDSDInt8NER8 = 40,
|
||||
|
||||
ASIOSTLastEntry,
|
||||
};
|
||||
|
||||
struct ASIODriverInfo {
|
||||
long asioVersion;
|
||||
long driverVersion;
|
||||
char name[32];
|
||||
char errorMessage[124];
|
||||
void* sysRef;
|
||||
};
|
||||
|
||||
struct ASIOBufferInfo {
|
||||
ASIOBool isInput;
|
||||
long channelNum;
|
||||
void* buffers[2];
|
||||
};
|
||||
|
||||
struct ASIOChannelInfo {
|
||||
long channel;
|
||||
ASIOBool isInput;
|
||||
ASIOBool isActive;
|
||||
long channelGroup;
|
||||
ASIOSampleType type;
|
||||
char name[32];
|
||||
};
|
||||
|
||||
struct ASIOClockSource {
|
||||
long index;
|
||||
long associatedChannel;
|
||||
long associatedGroup;
|
||||
ASIOBool isCurrentSource;
|
||||
char name[32];
|
||||
};
|
||||
|
||||
struct ASIOTimeInfo {
|
||||
double speed;
|
||||
ASIOTimeStamp systemTime;
|
||||
ASIOSamples samplePosition;
|
||||
ASIOSampleRate sampleRate;
|
||||
unsigned long flags;
|
||||
char reserved[12];
|
||||
};
|
||||
enum : unsigned long {
|
||||
kSystemTimeValid = 1 << 0,
|
||||
kSamplePositionValid = 1 << 1,
|
||||
kSampleRateValid = 1 << 2,
|
||||
kSpeedValid = 1 << 3,
|
||||
kSampleRateChanged = 1 << 4,
|
||||
kClockSourceChanged = 1 << 5,
|
||||
};
|
||||
|
||||
struct ASIOTimeCode {
|
||||
double speed;
|
||||
ASIOSamples timeCodeSamples;
|
||||
unsigned long flags;
|
||||
char future[64];
|
||||
};
|
||||
enum : unsigned long {
|
||||
kTcValid = 1 << 0,
|
||||
kTcRunning = 1 << 1,
|
||||
kTcReverse = 1 << 2,
|
||||
kTcOnspeed = 1 << 3,
|
||||
kTcStill = 1 << 4,
|
||||
kTcSpeedValid = 1 << 8,
|
||||
};
|
||||
|
||||
struct ASIOTime {
|
||||
long reserved[4];
|
||||
ASIOTimeInfo timeInfo;
|
||||
ASIOTimeCode timeCode;
|
||||
};
|
||||
|
||||
struct ASIOCallbacks {
|
||||
auto (*bufferSwitch)(long doubleBufferIndex, ASIOBool directProcess) -> void;
|
||||
auto (*sampleRateDidChange)(ASIOSampleRate sRate) -> void;
|
||||
auto (*asioMessage)(long selector, long value, void* message, double* opt) -> long;
|
||||
auto (*bufferSwitchTimeInfo)(ASIOTime* params, long doubleBufferIndex, ASIOBool directProcess) -> ASIOTime*;
|
||||
};
|
||||
enum : long {
|
||||
kAsioSelectorSupported = 1,
|
||||
kAsioEngineVersion,
|
||||
kAsioResetRequest,
|
||||
kAsioBufferSizeChange,
|
||||
kAsioResyncRequest,
|
||||
kAsioLatenciesChanged,
|
||||
kAsioSupportsTimeInfo,
|
||||
kAsioSupportsTimeCode,
|
||||
kAsioMMCCommand,
|
||||
kAsioSupportsInputMonitor,
|
||||
kAsioSupportsInputGain,
|
||||
kAsioSupportsInputMeter,
|
||||
kAsioSupportsOutputGain,
|
||||
kAsioSupportsOutputMeter,
|
||||
kAsioOverload,
|
||||
kAsioNumMessageSelectors,
|
||||
};
|
||||
|
||||
struct IASIO : public IUnknown {
|
||||
virtual auto init(void* sysHandle) -> ASIOBool;
|
||||
virtual auto getDriverName(char* name) -> void;
|
||||
virtual auto getDriverVersion() -> long;
|
||||
virtual auto getErrorMessage(char* error) -> void;
|
||||
virtual auto start() -> ASIOError;
|
||||
virtual auto stop() -> ASIOError;
|
||||
virtual auto getChannels(long* numInputChannels, long* numOutputChannels) -> ASIOError = 0;
|
||||
virtual auto getLatencies(long* inputLatency, long* outputLatency) -> ASIOError = 0;
|
||||
virtual auto getBufferSize(long* minSize, long* maxSize, long* preferredSize, long* granularity) -> ASIOError = 0;
|
||||
virtual auto canSampleRate(ASIOSampleRate sampleRate) -> ASIOError = 0;
|
||||
virtual auto getSampleRate(ASIOSampleRate* sampleRate) -> ASIOError = 0;
|
||||
virtual auto setSampleRate(ASIOSampleRate sampleRate) -> ASIOError = 0;
|
||||
virtual auto getClockSources(ASIOClockSource* clocks, long* numSources) -> ASIOError = 0;
|
||||
virtual auto setClockSource(long reference) -> ASIOError = 0;
|
||||
virtual auto getSamplePosition(ASIOSamples* sPos, ASIOTimeStamp* tStamp) -> ASIOError = 0;
|
||||
virtual auto getChannelInfo(ASIOChannelInfo* info) -> ASIOError = 0;
|
||||
virtual auto createBuffers(ASIOBufferInfo* bufferInfos, long numChannels, long bufferSize, ASIOCallbacks* callbacks) -> ASIOError = 0;
|
||||
virtual auto disposeBuffers() -> ASIOError = 0;
|
||||
virtual auto controlPanel() -> ASIOError = 0;
|
||||
virtual auto future(long selector, void* opt) -> ASIOError = 0;
|
||||
virtual auto outputReady() -> ASIOError = 0;
|
||||
};
|
@@ -1,7 +1,7 @@
|
||||
#include <dsound.h>
|
||||
|
||||
struct AudioDS : Audio {
|
||||
~AudioDS() { term(); }
|
||||
struct AudioDirectSound : Audio {
|
||||
~AudioDirectSound() { term(); }
|
||||
|
||||
LPDIRECTSOUND ds = nullptr;
|
||||
LPDIRECTSOUNDBUFFER dsb_p = nullptr;
|
||||
|
@@ -238,6 +238,10 @@ auto Video::availableDrivers() -> string_vector {
|
||||
#include <ruby/audio/ao.cpp>
|
||||
#endif
|
||||
|
||||
#if defined(AUDIO_ASIO)
|
||||
#include <ruby/audio/asio.cpp>
|
||||
#endif
|
||||
|
||||
#if defined(AUDIO_DIRECTSOUND)
|
||||
#include <ruby/audio/directsound.cpp>
|
||||
#endif
|
||||
@@ -286,8 +290,12 @@ auto Audio::create(const string& driver) -> Audio* {
|
||||
if(driver == "libao") return new AudioAO;
|
||||
#endif
|
||||
|
||||
#if defined(AUDIO_ASIO)
|
||||
if(driver == "ASIO") return new AudioASIO;
|
||||
#endif
|
||||
|
||||
#if defined(AUDIO_DIRECTSOUND)
|
||||
if(driver == "DirectSound") return new AudioDS;
|
||||
if(driver == "DirectSound") return new AudioDirectSound;
|
||||
#endif
|
||||
|
||||
#if defined(AUDIO_OPENAL)
|
||||
@@ -318,7 +326,9 @@ auto Audio::create(const string& driver) -> Audio* {
|
||||
}
|
||||
|
||||
auto Audio::optimalDriver() -> string {
|
||||
#if defined(AUDIO_WASAPI)
|
||||
#if defined(AUDIO_ASIO)
|
||||
return "ASIO";
|
||||
#elif defined(AUDIO_WASAPI)
|
||||
return "WASAPI";
|
||||
#elif defined(AUDIO_XAUDIO2)
|
||||
return "XAudio2";
|
||||
@@ -360,6 +370,8 @@ auto Audio::safestDriver() -> string {
|
||||
return "PulseAudioSimple";
|
||||
#elif defined(AUDIO_AO)
|
||||
return "libao";
|
||||
#elif defined(AUDIO_ASIO)
|
||||
return "ASIO";
|
||||
#else
|
||||
return "None";
|
||||
#endif
|
||||
@@ -368,6 +380,10 @@ auto Audio::safestDriver() -> string {
|
||||
auto Audio::availableDrivers() -> string_vector {
|
||||
return {
|
||||
|
||||
#if defined(AUDIO_ASIO)
|
||||
"ASIO",
|
||||
#endif
|
||||
|
||||
#if defined(AUDIO_WASAPI)
|
||||
"WASAPI",
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user