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