mirror of
https://github.com/libSDL2pp/libSDL2pp.git
synced 2025-09-09 15:28:29 -04:00
Merge branch 'audio-fixes'
This commit is contained in:
commit
9a245e073a
@ -32,19 +32,10 @@
|
||||
namespace SDL2pp {
|
||||
|
||||
class AudioSpec : public SDL_AudioSpec {
|
||||
public:
|
||||
typedef std::function<void(Uint8* stream, int len)> AudioCallback;
|
||||
|
||||
private:
|
||||
AudioCallback callback_;
|
||||
|
||||
private:
|
||||
static void SDLCallback(void *userdata, Uint8* stream, int len);
|
||||
|
||||
public:
|
||||
AudioSpec();
|
||||
AudioSpec(int freq, SDL_AudioFormat format, Uint8 channels, Uint16 samples, AudioCallback&& callback = AudioCallback());
|
||||
AudioSpec(const AudioSpec& other, AudioCallback&& callback = AudioCallback());
|
||||
AudioSpec(int freq, SDL_AudioFormat format, Uint8 channels, Uint16 samples);
|
||||
~AudioSpec();
|
||||
|
||||
AudioSpec(AudioSpec&& other);
|
||||
@ -52,8 +43,6 @@ public:
|
||||
AudioSpec(const AudioSpec& other) = delete;
|
||||
AudioSpec& operator=(const AudioSpec& other) = delete;
|
||||
|
||||
void ChangeCallback(AudioCallback&& callback); // should be called with audio device using this spec locked!
|
||||
|
||||
void MergeChanges(const SDL_AudioSpec& obtained);
|
||||
const SDL_AudioSpec* Get() const;
|
||||
|
||||
@ -61,9 +50,6 @@ public:
|
||||
};
|
||||
|
||||
class AudioDevice {
|
||||
private:
|
||||
SDL_AudioDeviceID device_id_;
|
||||
|
||||
public:
|
||||
class LockHandle {
|
||||
friend class AudioDevice;
|
||||
@ -74,6 +60,7 @@ public:
|
||||
LockHandle(AudioDevice* device);
|
||||
|
||||
public:
|
||||
LockHandle();
|
||||
~LockHandle();
|
||||
|
||||
LockHandle(LockHandle&& other) noexcept;
|
||||
@ -83,9 +70,18 @@ public:
|
||||
LockHandle& operator=(const LockHandle& other) = delete;
|
||||
};
|
||||
|
||||
typedef std::function<void(Uint8* stream, int len)> AudioCallback;
|
||||
|
||||
private:
|
||||
SDL_AudioDeviceID device_id_;
|
||||
AudioCallback callback_;
|
||||
|
||||
private:
|
||||
static void SDLCallback(void *userdata, Uint8* stream, int len);
|
||||
|
||||
public:
|
||||
AudioDevice(const std::string& device, bool iscapture, const AudioSpec& spec);
|
||||
AudioDevice(const std::string& device, bool iscapture, AudioSpec& spec, int allowed_changes);
|
||||
AudioDevice(const std::string& device, bool iscapture, const AudioSpec& spec, AudioCallback&& callback = AudioCallback());
|
||||
AudioDevice(const std::string& device, bool iscapture, AudioSpec& spec, int allowed_changes, AudioCallback&& callback = AudioCallback());
|
||||
virtual ~AudioDevice();
|
||||
|
||||
AudioDevice(const AudioDevice& other) = delete;
|
||||
@ -98,6 +94,8 @@ public:
|
||||
void Pause(bool pause_on);
|
||||
SDL_AudioStatus GetStatus() const;
|
||||
|
||||
void ChangeCallback(AudioCallback&& callback);
|
||||
|
||||
LockHandle Lock();
|
||||
|
||||
#ifdef SDL2PP_WITH_2_0_4
|
||||
|
@ -25,20 +25,39 @@
|
||||
|
||||
namespace SDL2pp {
|
||||
|
||||
AudioDevice::AudioDevice(const std::string& device, bool iscapture, const AudioSpec& spec) {
|
||||
SDL_AudioSpec obtained;
|
||||
|
||||
if ((device_id_ = SDL_OpenAudioDevice(device.empty() ? nullptr : device.c_str(), iscapture ? 1 : 0, &spec, &obtained, 0)) == 0)
|
||||
throw Exception("SDL_OpenAudioDevice failed");
|
||||
void AudioDevice::SDLCallback(void *userdata, Uint8* stream, int len) {
|
||||
AudioDevice* audiodevice = static_cast<AudioDevice*>(userdata);
|
||||
audiodevice->callback_(stream, len);
|
||||
}
|
||||
|
||||
AudioDevice::AudioDevice(const std::string& device, bool iscapture, AudioSpec& spec, int allowed_changes) {
|
||||
AudioDevice::AudioDevice(const std::string& device, bool iscapture, const AudioSpec& spec, AudioDevice::AudioCallback&& callback) {
|
||||
SDL_AudioSpec spec_with_callback = *spec.Get();
|
||||
if (callback) {
|
||||
spec_with_callback.callback = SDLCallback;
|
||||
spec_with_callback.userdata = static_cast<void*>(this);
|
||||
}
|
||||
SDL_AudioSpec obtained;
|
||||
|
||||
if ((device_id_ = SDL_OpenAudioDevice(device.empty() ? nullptr : device.c_str(), iscapture ? 1 : 0, &spec, &obtained, allowed_changes)) == 0)
|
||||
if ((device_id_ = SDL_OpenAudioDevice(device.empty() ? nullptr : device.c_str(), iscapture ? 1 : 0, &spec_with_callback, &obtained, 0)) == 0)
|
||||
throw Exception("SDL_OpenAudioDevice failed");
|
||||
|
||||
callback_ = std::move(callback);
|
||||
}
|
||||
|
||||
AudioDevice::AudioDevice(const std::string& device, bool iscapture, AudioSpec& spec, int allowed_changes, AudioDevice::AudioCallback&& callback) {
|
||||
SDL_AudioSpec spec_with_callback = *spec.Get();
|
||||
if (callback) {
|
||||
spec_with_callback.callback = SDLCallback;
|
||||
spec_with_callback.userdata = static_cast<void*>(this);
|
||||
}
|
||||
SDL_AudioSpec obtained;
|
||||
|
||||
if ((device_id_ = SDL_OpenAudioDevice(device.empty() ? nullptr : device.c_str(), iscapture ? 1 : 0, &spec_with_callback, &obtained, allowed_changes)) == 0)
|
||||
throw Exception("SDL_OpenAudioDevice failed");
|
||||
|
||||
spec.MergeChanges(obtained);
|
||||
|
||||
callback_ = std::move(callback);
|
||||
}
|
||||
|
||||
AudioDevice::~AudioDevice() {
|
||||
@ -46,7 +65,7 @@ AudioDevice::~AudioDevice() {
|
||||
SDL_CloseAudioDevice(device_id_);
|
||||
}
|
||||
|
||||
AudioDevice::AudioDevice(AudioDevice&& other) noexcept : device_id_(other.device_id_) {
|
||||
AudioDevice::AudioDevice(AudioDevice&& other) noexcept : device_id_(other.device_id_), callback_(std::move(other.callback_)) {
|
||||
other.device_id_ = 0;
|
||||
}
|
||||
|
||||
@ -58,6 +77,7 @@ AudioDevice& AudioDevice::operator=(AudioDevice&& other) noexcept {
|
||||
SDL_CloseAudioDevice(device_id_);
|
||||
|
||||
device_id_ = other.device_id_;
|
||||
callback_ = std::move(other.callback_);
|
||||
other.device_id_ = 0;
|
||||
|
||||
return *this;
|
||||
@ -75,6 +95,13 @@ SDL_AudioStatus AudioDevice::GetStatus() const {
|
||||
return SDL_GetAudioDeviceStatus(device_id_);
|
||||
}
|
||||
|
||||
void AudioDevice::ChangeCallback(AudioDevice::AudioCallback&& callback) {
|
||||
// make sure callback is not called while it's being replaced
|
||||
LockHandle lock = Lock();
|
||||
|
||||
callback_ = std::move(callback);
|
||||
}
|
||||
|
||||
AudioDevice::LockHandle AudioDevice::Lock() {
|
||||
return LockHandle(this);
|
||||
}
|
||||
|
@ -23,6 +23,9 @@
|
||||
|
||||
namespace SDL2pp {
|
||||
|
||||
AudioDevice::LockHandle::LockHandle() : device_(nullptr) {
|
||||
}
|
||||
|
||||
AudioDevice::LockHandle::LockHandle(AudioDevice* device) : device_(device) {
|
||||
SDL_LockAudioDevice(device_->device_id_);
|
||||
}
|
||||
|
@ -25,33 +25,16 @@
|
||||
|
||||
namespace SDL2pp {
|
||||
|
||||
void AudioSpec::SDLCallback(void *userdata, Uint8* stream, int len) {
|
||||
AudioSpec* audiospec = static_cast<AudioSpec*>(userdata);
|
||||
audiospec->callback_(stream, len);
|
||||
}
|
||||
|
||||
AudioSpec::AudioSpec() {
|
||||
std::fill((char*)this, (char*)this + sizeof(SDL_AudioSpec), 0);
|
||||
}
|
||||
|
||||
AudioSpec::AudioSpec(int freq, SDL_AudioFormat format, Uint8 channels, Uint16 samples, AudioSpec::AudioCallback&& callback)
|
||||
: callback_(std::move(callback)) {
|
||||
AudioSpec::AudioSpec(int freq, SDL_AudioFormat format, Uint8 channels, Uint16 samples) {
|
||||
std::fill((char*)this, (char*)this + sizeof(SDL_AudioSpec), 0);
|
||||
SDL_AudioSpec::freq = freq;
|
||||
SDL_AudioSpec::format = format;
|
||||
SDL_AudioSpec::channels = channels;
|
||||
SDL_AudioSpec::samples = samples;
|
||||
if (callback) {
|
||||
SDL_AudioSpec::callback = SDLCallback;
|
||||
SDL_AudioSpec::userdata = static_cast<void*>(this);
|
||||
}
|
||||
}
|
||||
|
||||
AudioSpec::AudioSpec(const AudioSpec& other, AudioSpec::AudioCallback&& callback) : SDL_AudioSpec(*other.Get()), callback_(std::move(callback)) {
|
||||
if (callback) {
|
||||
SDL_AudioSpec::callback = SDLCallback;
|
||||
SDL_AudioSpec::userdata = static_cast<void*>(this);
|
||||
}
|
||||
}
|
||||
|
||||
AudioSpec::~AudioSpec() {
|
||||
@ -60,10 +43,6 @@ AudioSpec::~AudioSpec() {
|
||||
AudioSpec::AudioSpec(AudioSpec&&) = default;
|
||||
AudioSpec& AudioSpec::operator=(AudioSpec&&) = default;
|
||||
|
||||
void AudioSpec::ChangeCallback(AudioCallback&& callback) {
|
||||
callback_ = callback;
|
||||
}
|
||||
|
||||
void AudioSpec::MergeChanges(const SDL_AudioSpec& obtained) {
|
||||
freq = obtained.freq;
|
||||
format = obtained.format;
|
||||
|
@ -35,16 +35,16 @@ int Run() {
|
||||
int64_t nsample = 0;
|
||||
|
||||
// Setup audio device, and provide callback which plays sine wave with specified frequency
|
||||
AudioSpec spec(samplerate, AUDIO_S16SYS, 1, 4096, [&nsample, frequency, samplerate](Uint8* stream, int len) {
|
||||
AudioSpec spec(samplerate, AUDIO_S16SYS, 1, 4096);
|
||||
|
||||
// Open audio device
|
||||
AudioDevice dev("", 0, spec, [&nsample, frequency, samplerate](Uint8* stream, int len) {
|
||||
// fill provided buffer with sine wave
|
||||
for (Uint8* ptr = stream; ptr < stream + len; ptr += 2)
|
||||
*(Uint16*)ptr = (Uint16)(32766.0f * sin(nsample++ / (float)samplerate * frequency));
|
||||
}
|
||||
);
|
||||
|
||||
// Open audio device
|
||||
AudioDevice dev("", 0, spec);
|
||||
|
||||
// Sound plays after this call
|
||||
dev.Pause(false);
|
||||
|
||||
|
@ -32,10 +32,10 @@ int Run() {
|
||||
SDL sdl(SDL_INIT_AUDIO);
|
||||
|
||||
Wav wav(TESTDATA_DIR "/test.wav");
|
||||
|
||||
// Setup audio device, and provide callback which plays looped wave sound
|
||||
Uint8* wav_pos = wav.GetBuffer();
|
||||
AudioSpec spec(wav.GetSpec(), [&wav, &wav_pos](Uint8* stream, int len) {
|
||||
|
||||
// Open audio device
|
||||
AudioDevice dev("", 0, wav.GetSpec(), [&wav, &wav_pos](Uint8* stream, int len) {
|
||||
// Fill provided buffer with wave contents
|
||||
Uint8* stream_pos = stream;
|
||||
Uint8* stream_end = stream + len;
|
||||
@ -54,13 +54,6 @@ int Run() {
|
||||
}
|
||||
);
|
||||
|
||||
// Open audio device
|
||||
AudioDevice dev("", 0, spec);
|
||||
|
||||
// Ensure SDL has set up format conversion for us
|
||||
if (!spec.IsSameFormat(wav.GetSpec()))
|
||||
throw std::runtime_error("WAV format is not the same as output format");
|
||||
|
||||
// Sound plays after this call
|
||||
dev.Pause(false);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user