Merge branch 'audio-fixes'

This commit is contained in:
Dmitry Marakasov 2014-12-18 17:28:02 +03:00
commit 9a245e073a
6 changed files with 61 additions and 61 deletions

View File

@ -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

View File

@ -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);
}

View File

@ -23,6 +23,9 @@
namespace SDL2pp {
AudioDevice::LockHandle::LockHandle() : device_(nullptr) {
}
AudioDevice::LockHandle::LockHandle(AudioDevice* device) : device_(device) {
SDL_LockAudioDevice(device_->device_id_);
}

View File

@ -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;

View File

@ -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);

View File

@ -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);