Mercurial > foo_out_sdl
view foo_out_sdl.cc @ 0:e9bb126753e7
*: initial commit
totally untested besides the wrapper; need to get msvc running
| author | Paper <paper@tflc.us> |
|---|---|
| date | Sat, 03 Jan 2026 23:52:56 -0500 |
| parents | |
| children | 20d02a178406 |
line wrap: on
line source
/* SDL output for foobar2000. * Somewhat scuffed since SDL does not provide latency */ #include <SDL3/SDL.h> #if audio_sample_size == 32 # define OUTSDL_USE_NATIVE_F32 1 # define OUTSDL_FORMAT SDL_AUDIO_F32 #else # define OUTSDL_FORMAT SDL_AUDIO_S32 #endif class OutputSDL : public output { public: OutputSDL(); ~OutputSDL(); virtual double get_latency() override; virtual void process_samples(const audio_chunk &p_chunk) override; virtual void update(bool &p_ready) override; virtual void pause(bool p_state) override; virtual void flush() override; virtual void force_play() override; virtual void volume_set(double p_val) override; private: void ReinitStream(unsigned int channels, unsigned int freq); SDL_AudioStream *stream_; #ifndef OUTSDL_USE_NATIVE_F32 std::vector<t_int32> buffer_; #endif SDL_AudioSpec spec_; HANDLE sdl_; #define FUNC(type, x, params, callparams) decltype(&SDL_##x) sdl3_##x; #include "foo_out_sdl_funcs.h" }; OutputSDL::OutputSDL() : sdl_(nullptr) , stream_(nullptr) #ifndef OUTSDL_USE_NATIVE_F32 /* sane default size */ , buffer_(8096) #endif { sdl_ = LoadLibraryA("foo_out_sdl_wrapper.dll"); if (!sdl3_) return; #define FUNC(type, x, params, callparams) \ sdl3_##x = (decltype(&SDL_##x))GetProcAddress(sdl_, "SDL_" #x); \ if (!sdl3_##x) \ return; #include "foo_out_sdl_funcs.h" // increment subsystem counter // hope this succeeds!!! sdl3_InitSubSystem(SDL_INIT_AUDIO); /* make a guess */ spec_.format = OUTSDL_FORMAT; spec_.channels = 2; /* Stereo is most likely. Who cares about surround? :) */ spec_.freq = 44100; /* guess CD quality */ // TODO supply output devices stream_ = sdl3_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &spec_, nullptr, nullptr); } OutputSDL::~OutputSDL() { if (sdl_ && stream_ && sdl3_DestroyAudioStream) sdl3_DestroyAudioStream(stream_); if (sdl_ && sdl3_QuitSubSystem) sdl3_QuitSubSystem(SDL_INIT_AUDIO); if (sdl_) FreeLibrary(sdl_); } void OutputSDL::ReinitStream(unsigned int channels, unsigned int freq) { // Fast path; no change // I'm assuming that the channel input config is the same for fb2k // and for SDL. This may not be the case. Whatever.. if (spec_.channels == channels && spec_.freq == freq) return; spec_.channels = channels; spec_.freq = freq; // tell SDL about our change sdl3_SetAudioStreamFormat(stream_, &spec_, nullptr); } virtual double OutputSDL::get_latency() { // TODO assume that one buffer's worth is queued return 0.016; // i guess } virtual void OutputSDL::process_samples(const audio_chunk &p_chunk) { // Reinitialize stream with possibly new values for channels and frequency ReinitStream(p_chunk.get_channels(), p_chunk.get_srate()); /* NOTE this is only actually tested with stereo */ #ifdef OUTSDL_USE_NATIVE_F32 /* audio_sample is 32-bit floating point; SDL can use this directly */ sdl3_PutAudioStreamData(stream_, p_chunk.get_data(), p_chunk.get_data_size()); #else /* Expand the buffer if necessary */ t_size sz = p_chunk.get_data_size(); if (sz > buffer_.size()) buffer_.resize(sz); /* Convert to int32 */ audio_math::convert_to_int32(p_chunk.get_data(), sz, buffer_.data(), buffer_.size()); /* Add int32 audio to stream */ sdl3_PutAudioStreamData(stream_, buffer_.data(), buffer_.size()); #endif } virtual void OutputSDL::update(bool &p_ready) { /* seems legit */ p_ready = (sdl3_GetAudioStreamQueued(stream_) == 0); } virtual void OutputSDL::pause(bool p_state) { if (p_state) { sdl3_PauseAudioStreamDevice(stream_); } else { sdl3_ResumeAudioStreamDevice(stream_); } } // . these are easy virtual void OutputSDL::flush() { sdl3_ClearAudioStream(stream_); } virtual void OutputSDL::force_play() { sdl3_FlushAudioStream(stream_); } virtual void OutputSDL::volume_set(double p_val) { sdl3_SetAudioStreamGain(stream_, p_val); } static output_factory_t<OutputSDL> g_output_sdl_factory; //////////////////////////////////////////////////////////////////////////////// const char *about = "Copyright (c) paper <paper@tflc.us>, 2026\n"; // very beta ;) DECLARE_COMPONENT_VERSION("SDL output", "0.1", about); VALIDATE_COMPONENT_FILENAME("foo_out_sdl.dll");
