aboutsummaryrefslogtreecommitdiffstats
path: root/Alc
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2019-04-26 15:58:25 -0700
committerChris Robinson <[email protected]>2019-04-26 15:58:25 -0700
commitf23ff0394d8ae58dc12f8d1076fe5cd9dfde383d (patch)
tree6ab98ccc85c76eb77bf8c533cdaae179fb0b6bd4 /Alc
parent348e01dc4bc16ac4543d54b722fb46dbdebcb1e3 (diff)
Specify the buffer size as itself instead of the period count
Certain backends don't need a buffer size to be a strict multiple of the period count, which allows a little more flexibility. The period/update size simply acts as the minimum request, which helps control CPU load by determining how often parameter and other pre-mixing updates are processed.
Diffstat (limited to 'Alc')
-rw-r--r--Alc/alc.cpp47
-rw-r--r--Alc/backends/alsa.cpp37
-rw-r--r--Alc/backends/base.cpp2
-rw-r--r--Alc/backends/coreaudio.cpp2
-rw-r--r--Alc/backends/dsound.cpp25
-rw-r--r--Alc/backends/jack.cpp10
-rw-r--r--Alc/backends/opensl.cpp27
-rw-r--r--Alc/backends/oss.cpp9
-rw-r--r--Alc/backends/portaudio.cpp5
-rw-r--r--Alc/backends/pulseaudio.cpp33
-rw-r--r--Alc/backends/qsa.cpp4
-rw-r--r--Alc/backends/sdl2.cpp4
-rw-r--r--Alc/backends/sndio.cpp16
-rw-r--r--Alc/backends/solaris.cpp5
-rw-r--r--Alc/backends/wasapi.cpp46
-rw-r--r--Alc/backends/winmm.cpp11
16 files changed, 130 insertions, 153 deletions
diff --git a/Alc/alc.cpp b/Alc/alc.cpp
index 27e926da..edea3846 100644
--- a/Alc/alc.cpp
+++ b/Alc/alc.cpp
@@ -1743,7 +1743,7 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
if(!loopback)
{
- device->NumUpdates = DEFAULT_NUM_UPDATES;
+ device->BufferSize = DEFAULT_UPDATE_SIZE * DEFAULT_NUM_UPDATES;
device->UpdateSize = DEFAULT_UPDATE_SIZE;
device->Frequency = DEFAULT_OUTPUT_RATE;
@@ -1754,21 +1754,24 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
{
freq = maxi(freq, MIN_OUTPUT_RATE);
- device->NumUpdates = (device->NumUpdates*freq + device->NumUpdates/2) /
- device->Frequency;
+ device->BufferSize = (device->BufferSize*freq + device->Frequency/2) /
+ device->Frequency;
device->Frequency = freq;
device->Flags |= DEVICE_FREQUENCY_REQUEST;
}
- ConfigValueUInt(devname, nullptr, "periods", &device->NumUpdates);
- device->NumUpdates = clampu(device->NumUpdates, 2, 16);
-
ConfigValueUInt(devname, nullptr, "period_size", &device->UpdateSize);
device->UpdateSize = clampu(device->UpdateSize, 64, 8192);
/* SSE and Neon do best with the update size being a multiple of 4. */
if((CPUCapFlags&(CPU_CAP_SSE|CPU_CAP_NEON)) != 0)
device->UpdateSize = (device->UpdateSize+3u)&~3u;
+
+ ALuint periods{};
+ if(ConfigValueUInt(devname, nullptr, "periods", &periods))
+ device->BufferSize = device->UpdateSize * clampu(periods, 2, 16);
+ else
+ device->BufferSize = maxu(device->BufferSize, device->UpdateSize*2);
}
else
{
@@ -1880,12 +1883,11 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
oldChans = device->FmtChans;
oldType = device->FmtType;
- TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u update size x%d\n",
+ TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u / %u buffer\n",
(device->Flags&DEVICE_CHANNELS_REQUEST)?"*":"", DevFmtChannelsString(device->FmtChans),
(device->Flags&DEVICE_SAMPLE_TYPE_REQUEST)?"*":"", DevFmtTypeString(device->FmtType),
(device->Flags&DEVICE_FREQUENCY_REQUEST)?"*":"", device->Frequency,
- device->UpdateSize, device->NumUpdates
- );
+ device->UpdateSize, device->BufferSize);
if(device->Backend->reset() == ALC_FALSE)
return ALC_INVALID_DEVICE;
@@ -1916,10 +1918,9 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
WARN("NEON performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize);
}
- TRACE("Post-reset: %s, %s, %uhz, %u update size x%d\n",
+ TRACE("Post-reset: %s, %s, %uhz, %u / %u buffer\n",
DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
- device->Frequency, device->UpdateSize, device->NumUpdates
- );
+ device->Frequency, device->UpdateSize, device->BufferSize);
aluInitRenderer(device, hrtf_id, hrtf_appreq, hrtf_userreq);
TRACE("Channel config, Main: %d, Real: %d\n", device->Dry.NumChannels,
@@ -3670,7 +3671,7 @@ START_API_FUNC
device->FmtType = DevFmtTypeDefault;
device->Frequency = DEFAULT_OUTPUT_RATE;
device->UpdateSize = DEFAULT_UPDATE_SIZE;
- device->NumUpdates = DEFAULT_NUM_UPDATES;
+ device->BufferSize = DEFAULT_UPDATE_SIZE * DEFAULT_NUM_UPDATES;
device->LimiterState = ALC_TRUE;
device->SourcesMax = 256;
@@ -3764,19 +3765,22 @@ START_API_FUNC
ERR("%uhz request clamped to %uhz minimum\n", freq, MIN_OUTPUT_RATE);
freq = MIN_OUTPUT_RATE;
}
- device->NumUpdates = (device->NumUpdates*freq + device->Frequency/2) / device->Frequency;
+ device->BufferSize = (device->BufferSize*freq + device->Frequency/2) / device->Frequency;
device->Frequency = freq;
device->Flags |= DEVICE_FREQUENCY_REQUEST;
}
- ConfigValueUInt(deviceName, nullptr, "periods", &device->NumUpdates);
- device->NumUpdates = clampu(device->NumUpdates, 2, 16);
-
ConfigValueUInt(deviceName, nullptr, "period_size", &device->UpdateSize);
device->UpdateSize = clampu(device->UpdateSize, 64, 8192);
if((CPUCapFlags&(CPU_CAP_SSE|CPU_CAP_NEON)) != 0)
device->UpdateSize = (device->UpdateSize+3u)&~3u;
+ ALuint periods{};
+ if(ConfigValueUInt(deviceName, nullptr, "periods", &periods))
+ device->BufferSize = device->UpdateSize * clampu(periods, 2, 16);
+ else
+ device->BufferSize = maxu(device->BufferSize, device->UpdateSize*2);
+
ConfigValueUInt(deviceName, nullptr, "sources", &device->SourcesMax);
if(device->SourcesMax == 0) device->SourcesMax = 256;
@@ -3927,7 +3931,7 @@ START_API_FUNC
device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_SAMPLE_TYPE_REQUEST;
device->UpdateSize = samples;
- device->NumUpdates = 1;
+ device->BufferSize = samples;
device->Backend = CaptureBackend.getFactory().createBackend(device.get(),
BackendType::Capture);
@@ -3937,10 +3941,9 @@ START_API_FUNC
return nullptr;
}
- TRACE("Capture format: %s, %s, %uhz, %u update size x%d\n",
+ TRACE("Capture format: %s, %s, %uhz, %u / %u buffer\n",
DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
- device->Frequency, device->UpdateSize, device->NumUpdates
- );
+ device->Frequency, device->UpdateSize, device->BufferSize);
ALCenum err{device->Backend->open(deviceName)};
if(err != ALC_NO_ERROR)
{
@@ -4082,7 +4085,7 @@ START_API_FUNC
device->NumAuxSends = DEFAULT_SENDS;
//Set output format
- device->NumUpdates = 0;
+ device->BufferSize = 0;
device->UpdateSize = 0;
device->Frequency = DEFAULT_OUTPUT_RATE;
diff --git a/Alc/backends/alsa.cpp b/Alc/backends/alsa.cpp
index 9f036a01..969708ab 100644
--- a/Alc/backends/alsa.cpp
+++ b/Alc/backends/alsa.cpp
@@ -421,8 +421,8 @@ int AlsaPlayback::mixerProc()
SetRTPriority();
althrd_setname(MIXER_THREAD_NAME);
- snd_pcm_uframes_t update_size{mDevice->UpdateSize};
- snd_pcm_uframes_t num_updates{mDevice->NumUpdates};
+ const snd_pcm_uframes_t update_size{mDevice->UpdateSize};
+ const snd_pcm_uframes_t num_updates{mDevice->BufferSize / update_size};
while(!mKillNow.load(std::memory_order_acquire))
{
int state{verify_state(mPcmHandle)};
@@ -504,8 +504,8 @@ int AlsaPlayback::mixerNoMMapProc()
SetRTPriority();
althrd_setname(MIXER_THREAD_NAME);
- snd_pcm_uframes_t update_size{mDevice->UpdateSize};
- snd_pcm_uframes_t num_updates{mDevice->NumUpdates};
+ const snd_pcm_uframes_t update_size{mDevice->UpdateSize};
+ const snd_pcm_uframes_t buffer_size{mDevice->BufferSize};
while(!mKillNow.load(std::memory_order_acquire))
{
int state{verify_state(mPcmHandle)};
@@ -523,7 +523,7 @@ int AlsaPlayback::mixerNoMMapProc()
continue;
}
- if(static_cast<snd_pcm_uframes_t>(avail) > update_size*num_updates)
+ if(static_cast<snd_pcm_uframes_t>(avail) > buffer_size)
{
WARN("available samples exceeds the buffer size\n");
snd_pcm_reset(mPcmHandle);
@@ -654,17 +654,18 @@ ALCboolean AlsaPlayback::reset()
}
bool allowmmap{!!GetConfigValueBool(mDevice->DeviceName.c_str(), "alsa", "mmap", 1)};
- ALuint periods{mDevice->NumUpdates};
ALuint periodLen{static_cast<ALuint>(mDevice->UpdateSize * 1000000_u64 / mDevice->Frequency)};
- ALuint bufferLen{periodLen * periods};
+ ALuint bufferLen{static_cast<ALuint>(mDevice->BufferSize * 1000000_u64 / mDevice->Frequency)};
ALuint rate{mDevice->Frequency};
- snd_pcm_uframes_t periodSizeInFrames;
+ snd_pcm_uframes_t periodSizeInFrames{};
+ snd_pcm_uframes_t bufferSizeInFrames{};
snd_pcm_sw_params_t *sp{};
snd_pcm_hw_params_t *hp{};
- snd_pcm_access_t access;
- const char *funcerr;
- int dir, err;
+ snd_pcm_access_t access{};
+ const char *funcerr{};
+ int err{};
+
snd_pcm_hw_params_malloc(&hp);
#define CHECK(x) if((funcerr=#x),(err=(x)) < 0) goto error
CHECK(snd_pcm_hw_params_any(mPcmHandle, hp));
@@ -745,22 +746,20 @@ ALCboolean AlsaPlayback::reset()
/* retrieve configuration info */
CHECK(snd_pcm_hw_params_get_access(hp, &access));
CHECK(snd_pcm_hw_params_get_period_size(hp, &periodSizeInFrames, nullptr));
- CHECK(snd_pcm_hw_params_get_periods(hp, &periods, &dir));
- if(dir != 0)
- WARN("Inexact period count: %u (%d)\n", periods, dir);
+ CHECK(snd_pcm_hw_params_get_buffer_size(hp, &bufferSizeInFrames));
snd_pcm_hw_params_free(hp);
hp = nullptr;
snd_pcm_sw_params_malloc(&sp);
CHECK(snd_pcm_sw_params_current(mPcmHandle, sp));
CHECK(snd_pcm_sw_params_set_avail_min(mPcmHandle, sp, periodSizeInFrames));
- CHECK(snd_pcm_sw_params_set_stop_threshold(mPcmHandle, sp, periodSizeInFrames*periods));
+ CHECK(snd_pcm_sw_params_set_stop_threshold(mPcmHandle, sp, bufferSizeInFrames));
CHECK(snd_pcm_sw_params(mPcmHandle, sp));
#undef CHECK
snd_pcm_sw_params_free(sp);
sp = nullptr;
- mDevice->NumUpdates = periods;
+ mDevice->BufferSize = bufferSizeInFrames;
mDevice->UpdateSize = periodSizeInFrames;
mDevice->Frequency = rate;
@@ -950,8 +949,7 @@ ALCenum AlsaCapture::open(const ALCchar *name)
break;
}
- snd_pcm_uframes_t bufferSizeInFrames{maxu(mDevice->UpdateSize*mDevice->NumUpdates,
- 100*mDevice->Frequency/1000)};
+ snd_pcm_uframes_t bufferSizeInFrames{maxu(mDevice->BufferSize, 100*mDevice->Frequency/1000)};
snd_pcm_uframes_t periodSizeInFrames{minu(bufferSizeInFrames, 25*mDevice->Frequency/1000)};
bool needring{false};
@@ -987,8 +985,7 @@ ALCenum AlsaCapture::open(const ALCchar *name)
if(needring)
{
- mRing = CreateRingBuffer(mDevice->UpdateSize*mDevice->NumUpdates,
- mDevice->frameSizeFromFmt(), false);
+ mRing = CreateRingBuffer(mDevice->BufferSize, mDevice->frameSizeFromFmt(), false);
if(!mRing)
{
ERR("ring buffer create failed\n");
diff --git a/Alc/backends/base.cpp b/Alc/backends/base.cpp
index ba5e5486..5239ae5b 100644
--- a/Alc/backends/base.cpp
+++ b/Alc/backends/base.cpp
@@ -51,7 +51,7 @@ ClockLatency BackendBase::getClockLatency()
* any given time during playback. Without a more accurate measurement from
* the output, this is an okay approximation.
*/
- ret.Latency = std::chrono::seconds{mDevice->UpdateSize*maxi(mDevice->NumUpdates-1, 0)};
+ ret.Latency = std::chrono::seconds{maxi(mDevice->BufferSize-mDevice->UpdateSize, 0)};
ret.Latency /= mDevice->Frequency;
return ret;
diff --git a/Alc/backends/coreaudio.cpp b/Alc/backends/coreaudio.cpp
index ce4bf600..d8b4500e 100644
--- a/Alc/backends/coreaudio.cpp
+++ b/Alc/backends/coreaudio.cpp
@@ -177,7 +177,7 @@ ALCboolean CoreAudioPlayback::reset()
if(mDevice->Frequency != streamFormat.mSampleRate)
{
- mDevice->NumUpdates = static_cast<ALuint>(uint64_t{mDevice->NumUpdates} *
+ mDevice->BufferSize = static_cast<ALuint>(uint64_t{mDevice->BufferSize} *
streamFormat.mSampleRate / mDevice->Frequency);
mDevice->Frequency = streamFormat.mSampleRate;
}
diff --git a/Alc/backends/dsound.cpp b/Alc/backends/dsound.cpp
index 00deafc1..38b1b9f8 100644
--- a/Alc/backends/dsound.cpp
+++ b/Alc/backends/dsound.cpp
@@ -496,19 +496,16 @@ retry_open:
if(SUCCEEDED(hr))
{
- if(mDevice->NumUpdates > MAX_UPDATES)
- {
- mDevice->UpdateSize = (mDevice->UpdateSize*mDevice->NumUpdates + MAX_UPDATES-1) /
- MAX_UPDATES;
- mDevice->NumUpdates = MAX_UPDATES;
- }
+ ALuint num_updates{mDevice->BufferSize / mDevice->UpdateSize};
+ if(num_updates > MAX_UPDATES)
+ num_updates = MAX_UPDATES;
+ mDevice->BufferSize = mDevice->UpdateSize * num_updates;
DSBUFFERDESC DSBDescription{};
DSBDescription.dwSize = sizeof(DSBDescription);
DSBDescription.dwFlags = DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_GETCURRENTPOSITION2 |
DSBCAPS_GLOBALFOCUS;
- DSBDescription.dwBufferBytes = mDevice->UpdateSize * mDevice->NumUpdates *
- OutputType.Format.nBlockAlign;
+ DSBDescription.dwBufferBytes = mDevice->BufferSize * OutputType.Format.nBlockAlign;
DSBDescription.lpwfxFormat = &OutputType.Format;
hr = mDS->CreateSoundBuffer(&DSBDescription, &mBuffer, nullptr);
@@ -528,15 +525,16 @@ retry_open:
auto Notifies = static_cast<IDirectSoundNotify*>(ptr);
mNotifies = Notifies;
- mDevice->NumUpdates = minu(mDevice->NumUpdates, MAX_UPDATES);
+ ALuint num_updates{mDevice->BufferSize / mDevice->UpdateSize};
+ assert(num_updates <= MAX_UPDATES);
std::array<DSBPOSITIONNOTIFY,MAX_UPDATES> nots;
- for(ALuint i{0};i < mDevice->NumUpdates;++i)
+ for(ALuint i{0};i < num_updates;++i)
{
nots[i].dwOffset = i * mDevice->UpdateSize * OutputType.Format.nBlockAlign;
nots[i].hEventNotify = mNotifyEvent;
}
- if(Notifies->SetNotificationPositions(mDevice->NumUpdates, nots.data()) != DS_OK)
+ if(Notifies->SetNotificationPositions(num_updates, nots.data()) != DS_OK)
hr = E_FAIL;
}
}
@@ -743,7 +741,7 @@ ALCenum DSoundCapture::open(const ALCchar *name)
InputType.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
}
- ALuint samples{mDevice->UpdateSize * mDevice->NumUpdates};
+ ALuint samples{mDevice->BufferSize};
samples = maxu(samples, 100 * mDevice->Frequency / 1000);
DSCBUFFERDESC DSCBDescription{};
@@ -758,8 +756,7 @@ ALCenum DSoundCapture::open(const ALCchar *name)
mDSC->CreateCaptureBuffer(&DSCBDescription, &mDSCbuffer, nullptr);
if(SUCCEEDED(hr))
{
- mRing = CreateRingBuffer(mDevice->UpdateSize*mDevice->NumUpdates,
- InputType.Format.nBlockAlign, false);
+ mRing = CreateRingBuffer(mDevice->BufferSize, InputType.Format.nBlockAlign, false);
if(!mRing) hr = DSERR_OUTOFMEMORY;
}
diff --git a/Alc/backends/jack.cpp b/Alc/backends/jack.cpp
index 77d5fea0..74364f6a 100644
--- a/Alc/backends/jack.cpp
+++ b/Alc/backends/jack.cpp
@@ -202,14 +202,14 @@ int JackPlayback::bufferSizeNotify(jack_nframes_t numframes)
{
std::lock_guard<std::mutex> _{mDevice->StateLock};
mDevice->UpdateSize = numframes;
- mDevice->NumUpdates = 2;
+ mDevice->BufferSize = numframes*2;
ALuint bufsize{mDevice->UpdateSize};
if(ConfigValueUInt(mDevice->DeviceName.c_str(), "jack", "buffer-size", &bufsize))
bufsize = maxu(NextPowerOf2(bufsize), mDevice->UpdateSize);
- mDevice->NumUpdates = (bufsize+mDevice->UpdateSize) / mDevice->UpdateSize;
+ mDevice->BufferSize = bufsize + mDevice->UpdateSize;
- TRACE("%u update size x%u\n", mDevice->UpdateSize, mDevice->NumUpdates);
+ TRACE("%u / %u buffer\n", mDevice->UpdateSize, mDevice->BufferSize);
mRing = nullptr;
mRing = CreateRingBuffer(bufsize, mDevice->frameSizeFromFmt(), true);
@@ -373,12 +373,12 @@ ALCboolean JackPlayback::reset()
*/
mDevice->Frequency = jack_get_sample_rate(mClient);
mDevice->UpdateSize = jack_get_buffer_size(mClient);
- mDevice->NumUpdates = 2;
+ mDevice->BufferSize = mDevice->UpdateSize * 2;
ALuint bufsize{mDevice->UpdateSize};
if(ConfigValueUInt(mDevice->DeviceName.c_str(), "jack", "buffer-size", &bufsize))
bufsize = maxu(NextPowerOf2(bufsize), mDevice->UpdateSize);
- mDevice->NumUpdates = (bufsize+mDevice->UpdateSize) / mDevice->UpdateSize;
+ mDevice->BufferSize = bufsize + mDevice->UpdateSize;
/* Force 32-bit float output. */
mDevice->FmtType = DevFmtFloat;
diff --git a/Alc/backends/opensl.cpp b/Alc/backends/opensl.cpp
index e3360362..818b381b 100644
--- a/Alc/backends/opensl.cpp
+++ b/Alc/backends/opensl.cpp
@@ -352,7 +352,6 @@ ALCboolean OpenSLPlayback::reset()
SLDataLocator_OutputMix loc_outmix;
SLDataSource audioSrc;
SLDataSink audioSnk;
- ALuint sampleRate;
SLInterfaceID ids[2];
SLboolean reqs[2];
SLresult result;
@@ -363,7 +362,6 @@ ALCboolean OpenSLPlayback::reset()
mRing = nullptr;
- sampleRate = mDevice->Frequency;
#if 0
if(!(mDevice->Flags&DEVICE_FREQUENCY_REQUEST))
{
@@ -432,14 +430,6 @@ ALCboolean OpenSLPlayback::reset()
}
#endif
- if(sampleRate != mDevice->Frequency)
- {
- mDevice->NumUpdates = (mDevice->NumUpdates*sampleRate + (mDevice->Frequency>>1)) /
- mDevice->Frequency;
- mDevice->NumUpdates = maxu(mDevice->NumUpdates, 2);
- mDevice->Frequency = sampleRate;
- }
-
mDevice->FmtChans = DevFmtStereo;
mDevice->FmtType = DevFmtShort;
@@ -448,7 +438,7 @@ ALCboolean OpenSLPlayback::reset()
loc_bufq.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE;
- loc_bufq.numBuffers = mDevice->NumUpdates;
+ loc_bufq.numBuffers = mDevice->BufferSize / mDevice->UpdateSize;
#ifdef SL_DATAFORMAT_PCM_EX
SLDataFormat_PCM_EX format_pcm;
@@ -514,12 +504,13 @@ ALCboolean OpenSLPlayback::reset()
}
if(SL_RESULT_SUCCESS == result)
{
+ const ALuint num_updates{mDevice->BufferSize / mDevice->UpdateSize};
try {
- mRing = CreateRingBuffer(mDevice->NumUpdates, mFrameSize*mDevice->UpdateSize, true);
+ mRing = CreateRingBuffer(num_updates, mFrameSize*mDevice->UpdateSize, true);
}
catch(std::exception& e) {
ERR("Failed allocating ring buffer %ux%ux%u: %s\n", mDevice->UpdateSize,
- mDevice->NumUpdates, mFrameSize, e.what());
+ num_updates, mFrameSize, e.what());
result = SL_RESULT_MEMORY_FAILURE;
}
}
@@ -694,17 +685,17 @@ ALCenum OpenSLCapture::open(const ALCchar* name)
{
mFrameSize = mDevice->frameSizeFromFmt();
/* Ensure the total length is at least 100ms */
- ALsizei length{maxi(mDevice->NumUpdates*mDevice->UpdateSize, mDevice->Frequency/10)};
+ ALsizei length{maxi(mDevice->BufferSize, mDevice->Frequency/10)};
/* Ensure the per-chunk length is at least 10ms, and no more than 50ms. */
- ALsizei update_len{clampi(mDevice->NumUpdates*mDevice->UpdateSize / 3,
- mDevice->Frequency/100, mDevice->Frequency/100*5)};
+ ALsizei update_len{clampi(mDevice->BufferSize/3, mDevice->Frequency/100,
+ mDevice->Frequency/100*5)};
ALsizei num_updates{(length+update_len-1) / update_len};
try {
mRing = CreateRingBuffer(num_updates, update_len*mFrameSize, false);
mDevice->UpdateSize = update_len;
- mDevice->NumUpdates = mRing->writeSpace();
+ mDevice->BufferSize = mRing->writeSpace() * update_len;
}
catch(std::exception& e) {
ERR("Failed to allocate ring buffer: %s\n", e.what());
@@ -728,7 +719,7 @@ ALCenum OpenSLCapture::open(const ALCchar* name)
SLDataLocator_AndroidSimpleBufferQueue loc_bq{};
loc_bq.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE;
- loc_bq.numBuffers = mDevice->NumUpdates;
+ loc_bq.numBuffers = mDevice->BufferSize / mDevice->UpdateSize;
#ifdef SL_DATAFORMAT_PCM_EX
SLDataFormat_PCM_EX format_pcm{};
diff --git a/Alc/backends/oss.cpp b/Alc/backends/oss.cpp
index ccc59c39..cc385edf 100644
--- a/Alc/backends/oss.cpp
+++ b/Alc/backends/oss.cpp
@@ -391,7 +391,7 @@ ALCboolean OSSPlayback::reset()
break;
}
- periods = mDevice->NumUpdates;
+ periods = mDevice->BufferSize / mDevice->UpdateSize;
numChannels = mDevice->channelsFromFmt();
ossSpeed = mDevice->Frequency;
frameSize = numChannels * mDevice->bytesFromFmt();
@@ -436,7 +436,7 @@ ALCboolean OSSPlayback::reset()
mDevice->Frequency = ossSpeed;
mDevice->UpdateSize = info.fragsize / frameSize;
- mDevice->NumUpdates = info.fragments;
+ mDevice->BufferSize = info.fragments * mDevice->UpdateSize;
SetDefaultChannelOrder(mDevice);
@@ -598,8 +598,7 @@ ALCenum OSScapture::open(const ALCchar *name)
int numChannels{mDevice->channelsFromFmt()};
int frameSize{numChannels * mDevice->bytesFromFmt()};
int ossSpeed{static_cast<int>(mDevice->Frequency)};
- int log2FragmentSize{log2i(mDevice->UpdateSize * mDevice->NumUpdates *
- frameSize / periods)};
+ int log2FragmentSize{log2i(mDevice->BufferSize * frameSize / periods)};
/* according to the OSS spec, 16 bytes are the minimum */
log2FragmentSize = std::max(log2FragmentSize, 4);
@@ -645,7 +644,7 @@ ALCenum OSScapture::open(const ALCchar *name)
return ALC_INVALID_VALUE;
}
- mRing = CreateRingBuffer(mDevice->UpdateSize*mDevice->NumUpdates, frameSize, false);
+ mRing = CreateRingBuffer(mDevice->BufferSize, frameSize, false);
if(!mRing)
{
ERR("Ring buffer create failed\n");
diff --git a/Alc/backends/portaudio.cpp b/Alc/backends/portaudio.cpp
index 07f2b2d5..6df98434 100644
--- a/Alc/backends/portaudio.cpp
+++ b/Alc/backends/portaudio.cpp
@@ -133,8 +133,7 @@ ALCenum PortPlayback::open(const ALCchar *name)
mParams.device = -1;
if(!ConfigValueInt(nullptr, "port", "device", &mParams.device) || mParams.device < 0)
mParams.device = Pa_GetDefaultOutputDevice();
- mParams.suggestedLatency = (mDevice->UpdateSize*mDevice->NumUpdates) /
- static_cast<float>(mDevice->Frequency);
+ mParams.suggestedLatency = mDevice->BufferSize / static_cast<double>(mDevice->Frequency);
mParams.hostApiSpecificStreamInfo = nullptr;
mParams.channelCount = ((mDevice->FmtChans == DevFmtMono) ? 1 : 2);
@@ -294,7 +293,7 @@ ALCenum PortCapture::open(const ALCchar *name)
else if(strcmp(name, pa_device) != 0)
return ALC_INVALID_VALUE;
- ALuint samples{mDevice->UpdateSize * mDevice->NumUpdates};
+ ALuint samples{mDevice->BufferSize};
samples = maxu(samples, 100 * mDevice->Frequency / 1000);
ALsizei frame_size{mDevice->frameSizeFromFmt()};
diff --git a/Alc/backends/pulseaudio.cpp b/Alc/backends/pulseaudio.cpp
index fad6e8b4..29fd5ae9 100644
--- a/Alc/backends/pulseaudio.cpp
+++ b/Alc/backends/pulseaudio.cpp
@@ -691,7 +691,7 @@ void PulsePlayback::bufferAttrCallbackC(pa_stream *stream, void *pdata)
void PulsePlayback::bufferAttrCallback(pa_stream *stream)
{
- /* FIXME: Update the device's UpdateSize (and/or NumUpdates) using the new
+ /* FIXME: Update the device's UpdateSize (and/or BufferSize) using the new
* buffer attributes? Changing UpdateSize will change the ALC_REFRESH
* property, which probably shouldn't change between device resets. But
* leaving it alone means ALC_REFRESH will be off.
@@ -1007,11 +1007,10 @@ ALCboolean PulsePlayback::reset()
}
SetDefaultWFXChannelOrder(mDevice);
- size_t period_size{mDevice->UpdateSize * pa_frame_size(&mSpec)};
mAttr.maxlength = -1;
- mAttr.tlength = period_size * maxu(mDevice->NumUpdates, 2);
+ mAttr.tlength = mDevice->BufferSize * pa_frame_size(&mSpec);
mAttr.prebuf = 0;
- mAttr.minreq = period_size;
+ mAttr.minreq = mDevice->UpdateSize * pa_frame_size(&mSpec);
mAttr.fragsize = -1;
mStream = pulse_connect_stream(mDeviceName.c_str(), mLoop, mContext, flags, &mAttr, &mSpec,
@@ -1028,14 +1027,14 @@ ALCboolean PulsePlayback::reset()
{
/* Server updated our playback rate, so modify the buffer attribs
* accordingly. */
- mDevice->NumUpdates = static_cast<ALuint>(clampd(
- static_cast<ALdouble>(mSpec.rate)/mDevice->Frequency*mDevice->NumUpdates + 0.5, 2.0, 16.0));
+ double newlen{clampd(
+ static_cast<double>(mSpec.rate)/mDevice->Frequency*mDevice->BufferSize + 0.5,
+ mDevice->UpdateSize*2, std::numeric_limits<int>::max()/mFrameSize)};
- period_size = mDevice->UpdateSize * mFrameSize;
mAttr.maxlength = -1;
- mAttr.tlength = period_size * maxu(mDevice->NumUpdates, 2);
+ mAttr.tlength = static_cast<ALuint>(newlen) * mFrameSize;
mAttr.prebuf = 0;
- mAttr.minreq = period_size;
+ mAttr.minreq = mDevice->UpdateSize * mFrameSize;
op = pa_stream_set_buffer_attr(mStream, &mAttr, stream_success_callback, mLoop);
wait_for_operation(op, mLoop);
@@ -1046,7 +1045,7 @@ ALCboolean PulsePlayback::reset()
pa_stream_set_buffer_attr_callback(mStream, &PulsePlayback::bufferAttrCallbackC, this);
bufferAttrCallback(mStream);
- mDevice->NumUpdates = clampu((mAttr.tlength + mAttr.minreq/2u) / mAttr.minreq, 2u, 16u);
+ mDevice->BufferSize = mAttr.tlength / mFrameSize;
mDevice->UpdateSize = mAttr.minreq / mFrameSize;
/* HACK: prebuf should be 0 as that's what we set it to. However on some
@@ -1058,15 +1057,9 @@ ALCboolean PulsePlayback::reset()
if(mAttr.prebuf != 0)
{
ALuint len{mAttr.prebuf / mFrameSize};
- if(len <= mDevice->UpdateSize*mDevice->NumUpdates)
+ if(len <= mDevice->BufferSize)
ERR("Non-0 prebuf, %u samples (%u bytes), device has %u samples\n",
- len, mAttr.prebuf, mDevice->UpdateSize*mDevice->NumUpdates);
- else
- {
- ERR("Large prebuf, %u samples (%u bytes), increasing device from %u samples",
- len, mAttr.prebuf, mDevice->UpdateSize*mDevice->NumUpdates);
- mDevice->NumUpdates = (len+mDevice->UpdateSize-1) / mDevice->UpdateSize;
- }
+ len, mAttr.prebuf, mDevice->BufferSize);
}
return ALC_TRUE;
@@ -1328,7 +1321,7 @@ ALCenum PulseCapture::open(const ALCchar *name)
return ALC_INVALID_VALUE;
}
- ALuint samples{mDevice->UpdateSize * mDevice->NumUpdates};
+ ALuint samples{mDevice->BufferSize};
samples = maxu(samples, 100 * mDevice->Frequency / 1000);
mAttr.minreq = -1;
@@ -1337,7 +1330,7 @@ ALCenum PulseCapture::open(const ALCchar *name)
mAttr.tlength = -1;
mAttr.fragsize = minu(samples, 50*mDevice->Frequency/1000) * pa_frame_size(&mSpec);
- pa_stream_flags_t flags{PA_STREAM_START_CORKED|PA_STREAM_ADJUST_LATENCY};
+ pa_stream_flags_t flags{PA_STREAM_START_CORKED | PA_STREAM_ADJUST_LATENCY};
if(!GetConfigValueBool(nullptr, "pulse", "allow-moves", 0))
flags |= PA_STREAM_DONT_MOVE;
diff --git a/Alc/backends/qsa.cpp b/Alc/backends/qsa.cpp
index ab5bef9a..534d5798 100644
--- a/Alc/backends/qsa.cpp
+++ b/Alc/backends/qsa.cpp
@@ -380,8 +380,8 @@ static ALCboolean qsa_reset_playback(PlaybackWrapper *self)
data->cparams.stop_mode=SND_PCM_STOP_STOP;
data->cparams.buf.block.frag_size=device->UpdateSize * device->frameSizeFromFmt();
- data->cparams.buf.block.frags_max=device->NumUpdates;
- data->cparams.buf.block.frags_min=device->NumUpdates;
+ data->cparams.buf.block.frags_max=device->BufferSize / device->UpdateSize;
+ data->cparams.buf.block.frags_min=data->cparams.buf.block.frags_max;
data->cparams.format.interleave=1;
data->cparams.format.rate=device->Frequency;
diff --git a/Alc/backends/sdl2.cpp b/Alc/backends/sdl2.cpp
index a1011735..51c927cc 100644
--- a/Alc/backends/sdl2.cpp
+++ b/Alc/backends/sdl2.cpp
@@ -146,7 +146,7 @@ ALCenum Sdl2Backend::open(const ALCchar *name)
return ALC_INVALID_VALUE;
}
mDevice->UpdateSize = have.samples;
- mDevice->NumUpdates = 2; /* SDL always (tries to) use two periods. */
+ mDevice->BufferSize = have.samples * 2; /* SDL always (tries to) use two periods. */
mFrameSize = mDevice->frameSizeFromFmt();
mFrequency = mDevice->Frequency;
@@ -164,7 +164,7 @@ ALCboolean Sdl2Backend::reset()
mDevice->FmtChans = mFmtChans;
mDevice->FmtType = mFmtType;
mDevice->UpdateSize = mUpdateSize;
- mDevice->NumUpdates = 2;
+ mDevice->BufferSize = mUpdateSize * 2;
SetDefaultWFXChannelOrder(mDevice);
return ALC_TRUE;
}
diff --git a/Alc/backends/sndio.cpp b/Alc/backends/sndio.cpp
index 1b869fe7..163dd2ff 100644
--- a/Alc/backends/sndio.cpp
+++ b/Alc/backends/sndio.cpp
@@ -164,7 +164,7 @@ ALCboolean SndioPlayback::reset()
par.le = SIO_LE_NATIVE;
par.round = mDevice->UpdateSize;
- par.appbufsz = mDevice->UpdateSize * (mDevice->NumUpdates-1);
+ par.appbufsz = mDevice->BufferSize - mDevice->UpdateSize;
if(!par.appbufsz) par.appbufsz = mDevice->UpdateSize;
if(!sio_setpar(mSndHandle, &par) || !sio_getpar(mSndHandle, &par))
@@ -203,7 +203,7 @@ ALCboolean SndioPlayback::reset()
SetDefaultChannelOrder(mDevice);
mDevice->UpdateSize = par.round;
- mDevice->NumUpdates = (par.bufsz/par.round) + 1;
+ mDevice->BufferSize = par.bufsz + par.round;
mBuffer.resize(mDevice->UpdateSize * mDevice->frameSizeFromFmt());
std::fill(mBuffer.begin(), mBuffer.end(), 0);
@@ -374,12 +374,11 @@ ALCenum SndioCapture::open(const ALCchar *name)
par.rchan = mDevice->channelsFromFmt();
par.rate = mDevice->Frequency;
- par.appbufsz = maxu(mDevice->UpdateSize*mDevice->NumUpdates, (mDevice->Frequency+9)/10);
- par.round = clampu(par.appbufsz/mDevice->NumUpdates, (mDevice->Frequency+99)/100,
- (mDevice->Frequency+19)/20);
+ par.appbufsz = maxu(mDevice->BufferSize, mDevice->Frequency/10);
+ par.round = minu(par.appbufsz, mDevice->Frequency/40);
mDevice->UpdateSize = par.round;
- mDevice->NumUpdates = maxu(par.appbufsz/par.round, 1);
+ mDevice->BufferSize = par.appbufsz;
if(!sio_setpar(mSndHandle, &par) || !sio_getpar(mSndHandle, &par))
{
@@ -408,11 +407,10 @@ ALCenum SndioCapture::open(const ALCchar *name)
return ALC_INVALID_VALUE;
}
- mRing = CreateRingBuffer(mDevice->UpdateSize*mDevice->NumUpdates, par.bps*par.rchan, false);
+ mRing = CreateRingBuffer(mDevice->BufferSize, par.bps*par.rchan, false);
if(!mRing)
{
- ERR("Failed to allocate %u-byte ringbuffer\n",
- mDevice->UpdateSize*mDevice->NumUpdates*par.bps*par.rchan);
+ ERR("Failed to allocate %u-byte ringbuffer\n", mDevice->BufferSize*par.bps*par.rchan);
return ALC_OUT_OF_MEMORY;
}
diff --git a/Alc/backends/solaris.cpp b/Alc/backends/solaris.cpp
index dd41de3e..3e59a78c 100644
--- a/Alc/backends/solaris.cpp
+++ b/Alc/backends/solaris.cpp
@@ -196,7 +196,7 @@ ALCboolean SolarisBackend::reset()
}
ALsizei frameSize{numChannels * mDevice->bytesFromFmt()};
- info.play.buffer_size = mDevice->UpdateSize*mDevice->NumUpdates * frameSize;
+ info.play.buffer_size = mDevice->BufferSize * frameSize;
if(ioctl(mFd, AUDIO_SETINFO, &info) < 0)
{
@@ -222,7 +222,8 @@ ALCboolean SolarisBackend::reset()
}
mDevice->Frequency = info.play.sample_rate;
- mDevice->UpdateSize = (info.play.buffer_size/mDevice->NumUpdates) + 1;
+ mDevice->BufferSize = info.play.buffer_size / frameSize;
+ mDevice->UpdateSize = mDevice->BufferSize / 2;
SetDefaultChannelOrder(mDevice);
diff --git a/Alc/backends/wasapi.cpp b/Alc/backends/wasapi.cpp
index aa9341ce..e1a5b278 100644
--- a/Alc/backends/wasapi.cpp
+++ b/Alc/backends/wasapi.cpp
@@ -561,7 +561,7 @@ FORCE_ALIGN int WasapiPlayback::mixerProc()
althrd_setname(MIXER_THREAD_NAME);
const ALuint update_size{mDevice->UpdateSize};
- const UINT32 buffer_len{update_size * mDevice->NumUpdates};
+ const UINT32 buffer_len{mDevice->BufferSize};
while(!mKillNow.load(std::memory_order_relaxed))
{
UINT32 written;
@@ -789,8 +789,7 @@ HRESULT WasapiPlayback::resetProxy()
CoTaskMemFree(wfx);
wfx = nullptr;
- REFERENCE_TIME buf_time{ScaleCeil(mDevice->UpdateSize*mDevice->NumUpdates, REFTIME_PER_SEC,
- mDevice->Frequency)};
+ REFERENCE_TIME buf_time{mDevice->BufferSize * REFTIME_PER_SEC / mDevice->Frequency};
if(!(mDevice->Flags&DEVICE_FREQUENCY_REQUEST))
mDevice->Frequency = OutputType.Format.nSamplesPerSec;
@@ -968,8 +967,8 @@ HRESULT WasapiPlayback::resetProxy()
SetDefaultWFXChannelOrder(mDevice);
- hr = mClient->Initialize(AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_EVENTCALLBACK,
- buf_time, 0, &OutputType.Format, nullptr);
+ hr = mClient->Initialize(AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_EVENTCALLBACK, buf_time,
+ 0, &OutputType.Format, nullptr);
if(FAILED(hr))
{
ERR("Failed to initialize audio client: 0x%08lx\n", hr);
@@ -980,26 +979,24 @@ HRESULT WasapiPlayback::resetProxy()
REFERENCE_TIME min_per;
hr = mClient->GetDevicePeriod(&min_per, nullptr);
if(SUCCEEDED(hr))
- {
- min_len = (UINT32)ScaleCeil(min_per, mDevice->Frequency, REFTIME_PER_SEC);
- /* Find the nearest multiple of the period size to the update size */
- if(min_len < mDevice->UpdateSize)
- min_len *= maxu((mDevice->UpdateSize + min_len/2) / min_len, 1u);
hr = mClient->GetBufferSize(&buffer_len);
- }
if(FAILED(hr))
{
ERR("Failed to get audio buffer info: 0x%08lx\n", hr);
return hr;
}
+ min_len = (UINT32)ScaleCeil(min_per, mDevice->Frequency, REFTIME_PER_SEC);
+ /* Find the nearest multiple of the period size to the update size */
+ if(min_len < mDevice->UpdateSize)
+ min_len *= maxu((mDevice->UpdateSize + min_len/2) / min_len, 1u);
+
mDevice->UpdateSize = min_len;
- mDevice->NumUpdates = buffer_len / mDevice->UpdateSize;
- if(mDevice->NumUpdates <= 1)
+ mDevice->BufferSize = buffer_len;
+ if(mDevice->BufferSize <= mDevice->UpdateSize)
{
ERR("Audio client returned buffer_len < period*2; expect break up\n");
- mDevice->NumUpdates = 2;
- mDevice->UpdateSize = buffer_len / mDevice->NumUpdates;
+ mDevice->UpdateSize = buffer_len / 2;
}
hr = mClient->SetEventHandle(mNotifyEvent);
@@ -1351,12 +1348,9 @@ HRESULT WasapiCapture::resetProxy()
}
mClient = static_cast<IAudioClient*>(ptr);
- REFERENCE_TIME buf_time{ScaleCeil(mDevice->UpdateSize*mDevice->NumUpdates, REFTIME_PER_SEC,
- mDevice->Frequency)};
// Make sure buffer is at least 100ms in size
+ REFERENCE_TIME buf_time{mDevice->BufferSize * REFTIME_PER_SEC / mDevice->Frequency};
buf_time = maxu64(buf_time, REFTIME_PER_SEC/10);
- mDevice->UpdateSize = (ALuint)ScaleCeil(buf_time, mDevice->Frequency, REFTIME_PER_SEC) /
- mDevice->NumUpdates;
WAVEFORMATEXTENSIBLE OutputType;
OutputType.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
@@ -1533,8 +1527,8 @@ HRESULT WasapiCapture::resetProxy()
mDevice->Frequency, DevFmtTypeString(srcType), OutputType.Format.nSamplesPerSec);
}
- hr = mClient->Initialize(AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_EVENTCALLBACK,
- buf_time, 0, &OutputType.Format, nullptr);
+ hr = mClient->Initialize(AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_EVENTCALLBACK, buf_time,
+ 0, &OutputType.Format, nullptr);
if(FAILED(hr))
{
ERR("Failed to initialize audio client: 0x%08lx\n", hr);
@@ -1542,14 +1536,20 @@ HRESULT WasapiCapture::resetProxy()
}
UINT32 buffer_len;
- hr = mClient->GetBufferSize(&buffer_len);
+ REFERENCE_TIME min_per;
+ hr = mClient->GetDevicePeriod(&min_per, nullptr);
+ if(SUCCEEDED(hr))
+ hr = mClient->GetBufferSize(&buffer_len);
if(FAILED(hr))
{
ERR("Failed to get buffer size: 0x%08lx\n", hr);
return hr;
}
+ mDevice->UpdateSize = static_cast<ALuint>(ScaleCeil(min_per, mDevice->Frequency,
+ REFTIME_PER_SEC));
+ mDevice->BufferSize = buffer_len;
- buffer_len = maxu(mDevice->UpdateSize*mDevice->NumUpdates, buffer_len);
+ buffer_len = maxu(mDevice->BufferSize, buffer_len);
mRing = CreateRingBuffer(buffer_len, mDevice->frameSizeFromFmt(), false);
if(!mRing)
{
diff --git a/Alc/backends/winmm.cpp b/Alc/backends/winmm.cpp
index aa8db972..12fa02c4 100644
--- a/Alc/backends/winmm.cpp
+++ b/Alc/backends/winmm.cpp
@@ -265,10 +265,10 @@ retry_open:
ALCboolean WinMMPlayback::reset()
{
- mDevice->UpdateSize = static_cast<ALuint>(uint64_t{mDevice->UpdateSize} *
+ mDevice->BufferSize = static_cast<ALuint>(uint64_t{mDevice->BufferSize} *
mFormat.nSamplesPerSec / mDevice->Frequency);
- mDevice->UpdateSize = (mDevice->UpdateSize*mDevice->NumUpdates + 3) / 4;
- mDevice->NumUpdates = 4;
+ mDevice->BufferSize = (mDevice->BufferSize+3) & ~0x3;
+ mDevice->UpdateSize = mDevice->BufferSize / 4;
mDevice->Frequency = mFormat.nSamplesPerSec;
if(mFormat.wFormatTag == WAVE_FORMAT_IEEE_FLOAT)
@@ -523,9 +523,8 @@ ALCenum WinMMCapture::open(const ALCchar *name)
// Allocate circular memory buffer for the captured audio
// Make sure circular buffer is at least 100ms in size
- ALuint CapturedDataSize{mDevice->UpdateSize*mDevice->NumUpdates};
- CapturedDataSize = static_cast<ALuint>(
- std::max<size_t>(CapturedDataSize, BufferSize*mWaveBuffer.size()));
+ ALuint CapturedDataSize{mDevice->BufferSize};
+ CapturedDataSize = static_cast<ALuint>(maxz(CapturedDataSize, BufferSize*mWaveBuffer.size()));
mRing = CreateRingBuffer(CapturedDataSize, mFormat.nBlockAlign, false);
if(!mRing) return ALC_INVALID_VALUE;