ruby: preliminary SDL2 audio driver

このコミットが含まれているのは:
Luke Usher 2023-08-13 18:55:06 +01:00
コミット 93937e8603
3個のファイルの変更108行の追加0行の削除

ファイルの表示

@ -13,6 +13,7 @@ ifeq ($(ruby),)
# If we're in a posix shell, use pkg-config/pkg-check
pkg_check = $(if $(shell pkg-config $1 && echo 1),$2)
ruby += $(call pkg_check,sdl2,input.sdl)
ruby += $(call pkg_check,sdl2,audio.sdl)
endif
else ifeq ($(platform),macos)
ruby += video.cgl
@ -30,6 +31,7 @@ ifeq ($(ruby),)
ruby += input.xlib
ruby += $(call pkg_check,libudev,input.udev)
ruby += $(call pkg_check,sdl2,input.sdl)
ruby += $(call pkg_check,sdl2,audio.sdl)
else ifeq ($(platform),bsd)
pkg_check = $(if $(shell pkg-config $1 && echo 1),$2)
ruby += video.glx video.glx2 video.xshm
@ -41,6 +43,7 @@ ifeq ($(ruby),)
ruby += $(call pkg_check,ao,audio.ao)
ruby += input.uhid input.xlib
ruby += $(call pkg_check,sdl2,input.sdl)
ruby += $(call pkg_check,sdl2,audio.sdl)
endif
endif
@ -55,6 +58,7 @@ ifeq ($(call which,pkg-config),)
# TODO: add SDL2 cflags
else
ruby.flags += $(if $(findstring input.sdl,$(ruby)),$(shell pkg-config sdl2 --cflags))
ruby.flags += $(if $(findstring audio.sdl,$(ruby)),$(shell pkg-config sdl2 --cflags))
endif
ruby.options :=
@ -79,9 +83,11 @@ ifeq ($(platform),windows)
# TODO: add SDL2 ldflags
else
ruby.options += $(if $(findstring input.sdl,$(ruby)),$(shell pkg-config sdl2 --libs --static))
ruby.options += $(if $(findstring audio.sdl,$(ruby)),$(shell pkg-config sdl2 --libs --static))
endif
else
ruby.options += $(if $(findstring input.sdl,$(ruby)),$(shell pkg-config sdl2 --libs))
ruby.options += $(if $(findstring audio.sdl,$(ruby)),$(shell pkg-config sdl2 --libs))
endif
ruby.options += $(if $(findstring input.udev,$(ruby)),-ludev)

ファイルの表示

@ -42,6 +42,10 @@
#include <ruby/audio/xaudio2.cpp>
#endif
#if defined(AUDIO_SDL)
#include <ruby/audio/sdl.cpp>
#endif
namespace ruby {
auto Audio::setExclusive(bool exclusive) -> bool {
@ -186,6 +190,10 @@ auto Audio::create(string driver) -> bool {
if(driver == "XAudio 2.1") self.instance = new AudioXAudio2(*this);
#endif
#if defined(AUDIO_SDL)
if(driver == "SDL") self.instance = new AudioSDL(*this);
#endif
if(!self.instance) self.instance = new AudioDriver(*this);
return self.instance->create();
@ -206,6 +214,10 @@ auto Audio::hasDrivers() -> vector<string> {
"XAudio 2.1",
#endif
#if defined(AUDIO_SDL)
"SDL",
#endif
#if defined(AUDIO_DIRECTSOUND)
"DirectSound 7.0",
#endif
@ -248,6 +260,8 @@ auto Audio::optimalDriver() -> string {
return "ASIO";
#elif defined(AUDIO_XAUDIO2)
return "XAudio 2.1";
#elif defined(AUDIO_SDL)
return "SDL";
#elif defined(AUDIO_DIRECTSOUND)
return "DirectSound 7.0";
#elif defined(AUDIO_WAVEOUT)
@ -278,6 +292,8 @@ auto Audio::safestDriver() -> string {
return "WASAPI";
#elif defined(AUDIO_XAUDIO2)
return "XAudio 2.1";
#elif defined(AUDIO_SDL)
return "SDL";
#elif defined(AUDIO_ALSA)
return "ALSA";
#elif defined(AUDIO_OSS)

86
ruby/audio/sdl.cpp ノーマルファイル
ファイルの表示

@ -0,0 +1,86 @@
#include <SDL2/SDL.h>
struct AudioSDL : AudioDriver {
AudioSDL& self = *this;
AudioSDL(Audio& super) : AudioDriver(super) {}
~AudioSDL() { terminate(); }
auto create() -> bool override {
super.setChannels(2);
super.setFrequency(48000);
super.setLatency(0);
return initialize();
}
auto driver() -> string override { return "SDL"; }
auto ready() -> bool override { return _ready; }
auto hasBlocking() -> bool override { return true; }
auto hasDynamic() -> bool override { return true; }
auto hasFrequencies() -> vector<u32> override {
return {44100, 48000, 96000};
}
auto setFrequency(u32 frequency) -> bool override { return initialize(); }
auto setLatency(u32 latency) -> bool override { return initialize(); }
auto setBlocking(bool blocking) -> bool override { clear(); return true; }
auto clear() -> void override {
if(!ready()) return;
SDL_ClearQueuedAudio(_device);
}
auto output(const f64 samples[]) -> void override {
if(!ready()) return;
if(self.blocking) {
while(SDL_GetQueuedAudioSize(_device) > _bufferSize) {
//wait for audio to drain
}
}
std::unique_ptr<f32[]> output = std::make_unique<f32[]>(channels);
for(auto n : range(channels)) output[n] = samples[n];
SDL_QueueAudio(_device, &output[0], channels * sizeof(f32));
}
auto level() -> f64 override {
return SDL_GetQueuedAudioSize(_device) / ((f64)_bufferSize);
}
private:
auto initialize() -> bool {
terminate();
SDL_InitSubSystem(SDL_INIT_AUDIO);
SDL_AudioSpec want{}, have{};
want.freq = frequency;
want.format = AUDIO_F32SYS;
want.channels = 2;
want.samples = 4096;
_device = SDL_OpenAudioDevice(NULL,0,&want,&have,0);
frequency = have.freq;
channels = have.channels;
_bufferSize = have.size;
SDL_PauseAudioDevice(_device, 0);
_ready = true;
clear();
return true;
}
auto terminate() -> void {
_ready = false;
SDL_CloseAudioDevice(_device);
SDL_QuitSubSystem(SDL_INIT_AUDIO);
}
bool _ready = false;
SDL_AudioDeviceID _device = 0;
u32 _bufferSize = 0;
};