diff options
author | Chris Robinson <[email protected]> | 2019-04-26 15:58:25 -0700 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2019-04-26 15:58:25 -0700 |
commit | f23ff0394d8ae58dc12f8d1076fe5cd9dfde383d (patch) | |
tree | 6ab98ccc85c76eb77bf8c533cdaae179fb0b6bd4 /Alc | |
parent | 348e01dc4bc16ac4543d54b722fb46dbdebcb1e3 (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.cpp | 47 | ||||
-rw-r--r-- | Alc/backends/alsa.cpp | 37 | ||||
-rw-r--r-- | Alc/backends/base.cpp | 2 | ||||
-rw-r--r-- | Alc/backends/coreaudio.cpp | 2 | ||||
-rw-r--r-- | Alc/backends/dsound.cpp | 25 | ||||
-rw-r--r-- | Alc/backends/jack.cpp | 10 | ||||
-rw-r--r-- | Alc/backends/opensl.cpp | 27 | ||||
-rw-r--r-- | Alc/backends/oss.cpp | 9 | ||||
-rw-r--r-- | Alc/backends/portaudio.cpp | 5 | ||||
-rw-r--r-- | Alc/backends/pulseaudio.cpp | 33 | ||||
-rw-r--r-- | Alc/backends/qsa.cpp | 4 | ||||
-rw-r--r-- | Alc/backends/sdl2.cpp | 4 | ||||
-rw-r--r-- | Alc/backends/sndio.cpp | 16 | ||||
-rw-r--r-- | Alc/backends/solaris.cpp | 5 | ||||
-rw-r--r-- | Alc/backends/wasapi.cpp | 46 | ||||
-rw-r--r-- | Alc/backends/winmm.cpp | 11 |
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; |