1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 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;
};
|