From b68ad4ced2ce985c4e53b1469681ed3ec807d2b6 Mon Sep 17 00:00:00 2001 From: sudden6 Date: Wed, 12 Apr 2017 00:10:55 +0200 Subject: [PATCH] feat(audio): don't use dynamic memory allocation and remove resource leak --- src/audio/audio.cpp | 46 +++++++++++++++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 14 deletions(-) diff --git a/src/audio/audio.cpp b/src/audio/audio.cpp index 71c588597..a98b812cf 100644 --- a/src/audio/audio.cpp +++ b/src/audio/audio.cpp @@ -119,8 +119,13 @@ private: * * @var Audio::AUDIO_CHANNELS * @brief Ideally, we'd auto-detect, but that's a sane default + * + * @var BUFFER_COUNT + * @brief Number of buffers to use per audio source */ +static const unsigned int BUFFER_COUNT = 16; + /** * @brief Returns the singleton instance. */ @@ -480,32 +485,35 @@ void Audio::playAudioBuffer(ALuint alSource, const int16_t* data, int samples, u if (!(alOutDev && outputInitialized)) return; - ALuint bufid; - ALint processed = 0, queued = 16; + ALuint bufids[BUFFER_COUNT]; + ALint processed = 0, queued = 0; alGetSourcei(alSource, AL_BUFFERS_PROCESSED, &processed); alGetSourcei(alSource, AL_BUFFERS_QUEUED, &queued); alSourcei(alSource, AL_LOOPING, AL_FALSE); - if (processed) { - ALuint* bufids = new ALuint[processed]; - alSourceUnqueueBuffers(alSource, processed, bufids); - alDeleteBuffers(processed - 1, bufids + 1); - bufid = bufids[0]; - delete[] bufids; - } else if (queued < 16) { - alGenBuffers(1, &bufid); + if (processed == 0) { + if (queued >= BUFFER_COUNT) { + // reached limit, drop audio + return; + } + // create new buffer if none got free and we're below the limit + alGenBuffers(1, bufids); } else { - return; + // unqueue all processed buffers + alSourceUnqueueBuffers(alSource, processed, bufids); + // delete all but the first buffer, reuse first for new data + alDeleteBuffers(processed - 1, bufids + 1); } - alBufferData(bufid, (channels == 1) ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16, data, + alBufferData(bufids[0], (channels == 1) ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16, data, samples * 2 * channels, sampleRate); - alSourceQueueBuffers(alSource, 1, &bufid); + alSourceQueueBuffers(alSource, 1, bufids); ALint state; alGetSourcei(alSource, AL_SOURCE_STATE, &state); - if (state != AL_PLAYING) + if (state != AL_PLAYING) { alSourcePlay(alSource); + } } /** @@ -671,6 +679,16 @@ void Audio::unsubscribeOutput(ALuint& sid) if (sid) { if (alIsSource(sid)) { + // stop playing, marks all buffers as processed + alSourceStop(sid); + // unqueue all buffers from the source + ALint processed = 0; + alGetSourcei(sid, AL_BUFFERS_PROCESSED, &processed); + ALuint* bufids = new ALuint[processed]; + alSourceUnqueueBuffers(sid, processed, bufids); + // delete all buffers + alDeleteBuffers(processed, bufids); + delete[] bufids; alDeleteSources(1, &sid); qDebug() << "Audio source" << sid << "deleted. Sources active:" << outSources.size(); } else {