|
|
|
@ -119,8 +119,13 @@ private:
@@ -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
@@ -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]; |
|
|
|
|
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 { |
|
|
|
|
// unqueue all processed buffers
|
|
|
|
|
alSourceUnqueueBuffers(alSource, processed, bufids); |
|
|
|
|
// delete all but the first buffer, reuse first for new data
|
|
|
|
|
alDeleteBuffers(processed - 1, bufids + 1); |
|
|
|
|
bufid = bufids[0]; |
|
|
|
|
delete[] bufids; |
|
|
|
|
} else if (queued < 16) { |
|
|
|
|
alGenBuffers(1, &bufid); |
|
|
|
|
} else { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
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)
@@ -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 { |
|
|
|
|