diff options
-rw-r--r-- | Alc/alc.cpp | 2 | ||||
-rw-r--r-- | Alc/backends/alsa.cpp | 18 | ||||
-rw-r--r-- | Alc/backends/coreaudio.cpp | 20 | ||||
-rw-r--r-- | Alc/backends/dsound.cpp | 22 | ||||
-rw-r--r-- | Alc/backends/opensl.cpp | 48 | ||||
-rw-r--r-- | Alc/backends/oss.cpp | 15 | ||||
-rw-r--r-- | Alc/backends/portaudio.cpp | 18 | ||||
-rw-r--r-- | Alc/backends/sndio.cpp | 16 | ||||
-rw-r--r-- | Alc/backends/wasapi.cpp | 18 | ||||
-rw-r--r-- | Alc/backends/winmm.cpp | 13 | ||||
-rw-r--r-- | Alc/ringbuffer.cpp | 45 | ||||
-rw-r--r-- | Alc/ringbuffer.h | 53 |
12 files changed, 119 insertions, 169 deletions
diff --git a/Alc/alc.cpp b/Alc/alc.cpp index cbd586b8..fb7f9c67 100644 --- a/Alc/alc.cpp +++ b/Alc/alc.cpp @@ -2459,7 +2459,7 @@ ALCcontext_struct::~ALCcontext_struct() } TRACE("Freed " SZFMT " listener property object%s\n", count, (count==1)?"":"s"); - ll_ringbuffer_free(AsyncEvents); + delete AsyncEvents; AsyncEvents = nullptr; ALCdevice_DecRef(Device); diff --git a/Alc/backends/alsa.cpp b/Alc/backends/alsa.cpp index 606877a8..228cafe0 100644 --- a/Alc/backends/alsa.cpp +++ b/Alc/backends/alsa.cpp @@ -929,7 +929,7 @@ struct ALCcaptureAlsa final : public ALCbackend { al::vector<char> Buffer; bool DoCapture{false}; - ll_ringbuffer_t *Ring{nullptr}; + RingBufferPtr Ring{nullptr}; snd_pcm_sframes_t mLastAvail{0}; }; @@ -963,9 +963,6 @@ void ALCcaptureAlsa_Destruct(ALCcaptureAlsa *self) snd_pcm_close(self->PcmHandle); self->PcmHandle = nullptr; - ll_ringbuffer_free(self->Ring); - self->Ring = nullptr; - ALCbackend_Destruct(STATIC_CAST(ALCbackend, self)); self->~ALCcaptureAlsa(); } @@ -1068,8 +1065,8 @@ ALCenum ALCcaptureAlsa_open(ALCcaptureAlsa *self, const ALCchar *name) if(needring) { - self->Ring = ll_ringbuffer_create(device->UpdateSize*device->NumUpdates, - device->frameSizeFromFmt(), false); + self->Ring.reset(ll_ringbuffer_create(device->UpdateSize*device->NumUpdates, + device->frameSizeFromFmt(), false)); if(!self->Ring) { ERR("ring buffer create failed\n"); @@ -1086,7 +1083,6 @@ error: if(hp) snd_pcm_hw_params_free(hp); error2: - ll_ringbuffer_free(self->Ring); self->Ring = nullptr; snd_pcm_close(self->PcmHandle); self->PcmHandle = nullptr; @@ -1142,7 +1138,7 @@ ALCenum ALCcaptureAlsa_captureSamples(ALCcaptureAlsa *self, ALCvoid *buffer, ALC if(self->Ring) { - ll_ringbuffer_read(self->Ring, static_cast<char*>(buffer), samples); + ll_ringbuffer_read(self->Ring.get(), static_cast<char*>(buffer), samples); return ALC_NO_ERROR; } @@ -1235,7 +1231,7 @@ ALCuint ALCcaptureAlsa_availableSamples(ALCcaptureAlsa *self) while(avail > 0) { - auto vec = ll_ringbuffer_get_write_vector(self->Ring); + auto vec = ll_ringbuffer_get_write_vector(self->Ring.get()); if(vec.first.len == 0) break; snd_pcm_sframes_t amt{std::min<snd_pcm_sframes_t>(vec.first.len, avail)}; @@ -1263,11 +1259,11 @@ ALCuint ALCcaptureAlsa_availableSamples(ALCcaptureAlsa *self) continue; } - ll_ringbuffer_write_advance(self->Ring, amt); + ll_ringbuffer_write_advance(self->Ring.get(), amt); avail -= amt; } - return ll_ringbuffer_read_space(self->Ring); + return ll_ringbuffer_read_space(self->Ring.get()); } ClockLatency ALCcaptureAlsa_getClockLatency(ALCcaptureAlsa *self) diff --git a/Alc/backends/coreaudio.cpp b/Alc/backends/coreaudio.cpp index 228d1d76..aaaf6221 100644 --- a/Alc/backends/coreaudio.cpp +++ b/Alc/backends/coreaudio.cpp @@ -324,7 +324,7 @@ struct ALCcoreAudioCapture final : public ALCbackend { AudioBufferList *BufferList; // Buffer for data coming from the input device ALCvoid *ResampleBuffer; // Buffer for returned RingBuffer data when resampling - ll_ringbuffer_t *Ring; + RingBufferPtr Ring{nullptr}; }; static void ALCcoreAudioCapture_Construct(ALCcoreAudioCapture *self, ALCdevice *device); @@ -376,14 +376,10 @@ static void ALCcoreAudioCapture_Construct(ALCcoreAudioCapture *self, ALCdevice * self->AudioConverter = NULL; self->BufferList = NULL; self->ResampleBuffer = NULL; - self->Ring = NULL; } static void ALCcoreAudioCapture_Destruct(ALCcoreAudioCapture *self) { - ll_ringbuffer_free(self->Ring); - self->Ring = NULL; - free(self->ResampleBuffer); self->ResampleBuffer = NULL; @@ -420,7 +416,7 @@ static OSStatus ALCcoreAudioCapture_RecordProc(void *inRefCon, return err; } - ll_ringbuffer_write(self->Ring, self->BufferList->mBuffers[0].mData, inNumberFrames); + ll_ringbuffer_write(self->Ring.get(), self->BufferList->mBuffers[0].mData, inNumberFrames); return noErr; } @@ -432,7 +428,7 @@ static OSStatus ALCcoreAudioCapture_ConvertCallback(AudioConverterRef UNUSED(inA ALCcoreAudioCapture *self = reinterpret_cast<ALCcoreAudioCapture*>(inUserData); // Read from the ring buffer and store temporarily in a large buffer - ll_ringbuffer_read(self->Ring, self->ResampleBuffer, *ioNumberDataPackets); + ll_ringbuffer_read(self->Ring.get(), self->ResampleBuffer, *ioNumberDataPackets); // Set the input data ioData->mNumberBuffers = 1; @@ -666,18 +662,16 @@ static ALCenum ALCcoreAudioCapture_open(ALCcoreAudioCapture *self, const ALCchar if(self->BufferList == NULL) goto error; - self->Ring = ll_ringbuffer_create( + self->Ring.reset(ll_ringbuffer_create( (size_t)ceil(device->UpdateSize*self->SampleRateRatio*device->NumUpdates), - self->FrameSize, false - ); + self->FrameSize, false)); if(!self->Ring) goto error; device->DeviceName = name; return ALC_NO_ERROR; error: - ll_ringbuffer_free(self->Ring); - self->Ring = NULL; + self->Ring = nullptr; free(self->ResampleBuffer); self->ResampleBuffer = NULL; destroy_buffer_list(self->BufferList); @@ -745,7 +739,7 @@ static ALCenum ALCcoreAudioCapture_captureSamples(ALCcoreAudioCapture *self, ALC static ALCuint ALCcoreAudioCapture_availableSamples(ALCcoreAudioCapture *self) { - return ll_ringbuffer_read_space(self->Ring) / self->SampleRateRatio; + return ll_ringbuffer_read_space(self->Ring.get()) / self->SampleRateRatio; } diff --git a/Alc/backends/dsound.cpp b/Alc/backends/dsound.cpp index 5aa95f0f..26e561bf 100644 --- a/Alc/backends/dsound.cpp +++ b/Alc/backends/dsound.cpp @@ -655,7 +655,7 @@ struct ALCdsoundCapture final : public ALCbackend { DWORD BufferBytes{0u}; DWORD Cursor{0u}; - ll_ringbuffer_t *Ring{nullptr}; + RingBufferPtr Ring{nullptr}; }; void ALCdsoundCapture_Construct(ALCdsoundCapture *self, ALCdevice *device); @@ -681,9 +681,6 @@ void ALCdsoundCapture_Construct(ALCdsoundCapture *self, ALCdevice *device) void ALCdsoundCapture_Destruct(ALCdsoundCapture *self) { - ll_ringbuffer_free(self->Ring); - self->Ring = nullptr; - if(self->DSCbuffer) { self->DSCbuffer->Stop(); @@ -838,8 +835,8 @@ ALCenum ALCdsoundCapture_open(ALCdsoundCapture *self, const ALCchar *deviceName) self->DSC->CreateCaptureBuffer(&DSCBDescription, &self->DSCbuffer, nullptr); if(SUCCEEDED(hr)) { - self->Ring = ll_ringbuffer_create(device->UpdateSize*device->NumUpdates, - InputType.Format.nBlockAlign, false); + self->Ring.reset(ll_ringbuffer_create(device->UpdateSize*device->NumUpdates, + InputType.Format.nBlockAlign, false)); if(!self->Ring) hr = DSERR_OUTOFMEMORY; } @@ -847,7 +844,6 @@ ALCenum ALCdsoundCapture_open(ALCdsoundCapture *self, const ALCchar *deviceName) { ERR("Device init failed: 0x%08lx\n", hr); - ll_ringbuffer_free(self->Ring); self->Ring = nullptr; if(self->DSCbuffer) self->DSCbuffer->Release(); @@ -893,7 +889,7 @@ void ALCdsoundCapture_stop(ALCdsoundCapture *self) ALCenum ALCdsoundCapture_captureSamples(ALCdsoundCapture *self, ALCvoid *buffer, ALCuint samples) { - ll_ringbuffer_read(self->Ring, buffer, samples); + ll_ringbuffer_read(self->Ring.get(), buffer, samples); return ALC_NO_ERROR; } @@ -902,7 +898,7 @@ ALCuint ALCdsoundCapture_availableSamples(ALCdsoundCapture *self) ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; if(!device->Connected.load(std::memory_order_acquire)) - return static_cast<ALCuint>(ll_ringbuffer_read_space(self->Ring)); + return static_cast<ALCuint>(ll_ringbuffer_read_space(self->Ring.get())); ALsizei FrameSize{device->frameSizeFromFmt()}; DWORD BufferBytes{self->BufferBytes}; @@ -915,15 +911,15 @@ ALCuint ALCdsoundCapture_availableSamples(ALCdsoundCapture *self) if(SUCCEEDED(hr)) { DWORD NumBytes{(ReadCursor-LastCursor + BufferBytes) % BufferBytes}; - if(!NumBytes) return static_cast<ALCubyte>(ll_ringbuffer_read_space(self->Ring)); + if(!NumBytes) return static_cast<ALCubyte>(ll_ringbuffer_read_space(self->Ring.get())); hr = self->DSCbuffer->Lock(LastCursor, NumBytes, &ReadPtr1, &ReadCnt1, &ReadPtr2, &ReadCnt2, 0); } if(SUCCEEDED(hr)) { - ll_ringbuffer_write(self->Ring, ReadPtr1, ReadCnt1/FrameSize); + ll_ringbuffer_write(self->Ring.get(), ReadPtr1, ReadCnt1/FrameSize); if(ReadPtr2 != nullptr) - ll_ringbuffer_write(self->Ring, ReadPtr2, ReadCnt2/FrameSize); + ll_ringbuffer_write(self->Ring.get(), ReadPtr2, ReadCnt2/FrameSize); hr = self->DSCbuffer->Unlock(ReadPtr1, ReadCnt1, ReadPtr2, ReadCnt2); self->Cursor = (LastCursor+ReadCnt1+ReadCnt2) % BufferBytes; } @@ -934,7 +930,7 @@ ALCuint ALCdsoundCapture_availableSamples(ALCdsoundCapture *self) aluHandleDisconnect(device, "Failure retrieving capture data: 0x%lx", hr); } - return static_cast<ALCuint>(ll_ringbuffer_read_space(self->Ring)); + return static_cast<ALCuint>(ll_ringbuffer_read_space(self->Ring.get())); } } // namespace diff --git a/Alc/backends/opensl.cpp b/Alc/backends/opensl.cpp index 78212791..ab829e05 100644 --- a/Alc/backends/opensl.cpp +++ b/Alc/backends/opensl.cpp @@ -145,7 +145,7 @@ struct ALCopenslPlayback final : public ALCbackend { /* buffer queue player interfaces */ SLObjectItf mBufferQueueObj{nullptr}; - ll_ringbuffer_t *mRing{nullptr}; + RingBufferPtr mRing{nullptr}; al::semaphore mSem; ALsizei mFrameSize{0}; @@ -195,9 +195,6 @@ static void ALCopenslPlayback_Destruct(ALCopenslPlayback* self) self->mEngineObj = NULL; self->mEngine = NULL; - ll_ringbuffer_free(self->mRing); - self->mRing = NULL; - ALCbackend_Destruct(STATIC_CAST(ALCbackend, self)); self->~ALCopenslPlayback(); } @@ -216,7 +213,7 @@ static void ALCopenslPlayback_process(SLAndroidSimpleBufferQueueItf UNUSED(bq), * available for writing again, and wake up the mixer thread to mix and * queue more audio. */ - ll_ringbuffer_read_advance(self->mRing, 1); + ll_ringbuffer_read_advance(self->mRing.get(), 1); self->mSem.post(); } @@ -250,7 +247,7 @@ static int ALCopenslPlayback_mixerProc(ALCopenslPlayback *self) { size_t todo; - if(ll_ringbuffer_write_space(self->mRing) == 0) + if(ll_ringbuffer_write_space(self->mRing.get()) == 0) { SLuint32 state = 0; @@ -267,7 +264,7 @@ static int ALCopenslPlayback_mixerProc(ALCopenslPlayback *self) break; } - if(ll_ringbuffer_write_space(self->mRing) == 0) + if(ll_ringbuffer_write_space(self->mRing.get()) == 0) { ALCopenslPlayback_unlock(self); self->mSem.wait(); @@ -276,13 +273,13 @@ static int ALCopenslPlayback_mixerProc(ALCopenslPlayback *self) } } - auto data = ll_ringbuffer_get_write_vector(self->mRing); + auto data = ll_ringbuffer_get_write_vector(self->mRing.get()); aluMixData(device, data.first.buf, data.first.len*device->UpdateSize); if(data.second.len > 0) aluMixData(device, data.second.buf, data.second.len*device->UpdateSize); todo = data.first.len+data.second.len; - ll_ringbuffer_write_advance(self->mRing, todo); + ll_ringbuffer_write_advance(self->mRing.get(), todo); for(size_t i = 0;i < todo;i++) { @@ -380,8 +377,7 @@ static ALCboolean ALCopenslPlayback_reset(ALCopenslPlayback *self) VCALL0(self->mBufferQueueObj,Destroy)(); self->mBufferQueueObj = NULL; - ll_ringbuffer_free(self->mRing); - self->mRing = NULL; + self->mRing = nullptr; sampleRate = device->Frequency; #if 0 @@ -536,9 +532,8 @@ static ALCboolean ALCopenslPlayback_reset(ALCopenslPlayback *self) } if(SL_RESULT_SUCCESS == result) { - self->mRing = ll_ringbuffer_create(device->NumUpdates, - self->mFrameSize*device->UpdateSize, true - ); + self->mRing.reset(ll_ringbuffer_create(device->NumUpdates, + self->mFrameSize*device->UpdateSize, true)); if(!self->mRing) { ERR("Out of memory allocating ring buffer %ux%u %u\n", device->UpdateSize, @@ -564,7 +559,7 @@ static ALCboolean ALCopenslPlayback_start(ALCopenslPlayback *self) SLAndroidSimpleBufferQueueItf bufferQueue; SLresult result; - ll_ringbuffer_reset(self->mRing); + ll_ringbuffer_reset(self->mRing.get()); result = VCALL(self->mBufferQueueObj,GetInterface)(SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &bufferQueue); @@ -642,7 +637,8 @@ static ClockLatency ALCopenslPlayback_getClockLatency(ALCopenslPlayback *self) ALCopenslPlayback_lock(self); ret.ClockTime = GetDeviceClockTime(device); - ret.Latency = std::chrono::seconds{ll_ringbuffer_read_space(self->mRing)*device->UpdateSize}; + ret.Latency = std::chrono::seconds{ll_ringbuffer_read_space(self->mRing.get()) * + device->UpdateSize}; ret.Latency /= device->Frequency; ALCopenslPlayback_unlock(self); @@ -658,7 +654,7 @@ struct ALCopenslCapture final : public ALCbackend { /* recording interfaces */ SLObjectItf mRecordObj{nullptr}; - ll_ringbuffer_t *mRing{nullptr}; + RingBufferPtr mRing{nullptr}; ALCuint mSplOffset{0u}; ALsizei mFrameSize{0}; @@ -699,9 +695,6 @@ static void ALCopenslCapture_Destruct(ALCopenslCapture *self) self->mEngineObj = NULL; self->mEngine = NULL; - ll_ringbuffer_free(self->mRing); - self->mRing = NULL; - ALCbackend_Destruct(STATIC_CAST(ALCbackend, self)); self->~ALCopenslCapture(); } @@ -711,7 +704,7 @@ static void ALCopenslCapture_process(SLAndroidSimpleBufferQueueItf UNUSED(bq), v { ALCopenslCapture *self = static_cast<ALCopenslCapture*>(context); /* A new chunk has been written into the ring buffer, advance it. */ - ll_ringbuffer_write_advance(self->mRing, 1); + ll_ringbuffer_write_advance(self->mRing.get(), 1); } @@ -830,9 +823,8 @@ static ALCenum ALCopenslCapture_open(ALCopenslCapture *self, const ALCchar *name if(SL_RESULT_SUCCESS == result) { - self->mRing = ll_ringbuffer_create(device->NumUpdates, - device->UpdateSize*self->mFrameSize, false - ); + self->mRing.reset(ll_ringbuffer_create(device->NumUpdates, + device->UpdateSize*self->mFrameSize, false)); result = VCALL(self->mRecordObj,GetInterface)(SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &bufferQueue); @@ -848,7 +840,7 @@ static ALCenum ALCopenslCapture_open(ALCopenslCapture *self, const ALCchar *name ALsizei chunk_size = device->UpdateSize * self->mFrameSize; size_t i; - auto data = ll_ringbuffer_get_write_vector(self->mRing); + auto data = ll_ringbuffer_get_write_vector(self->mRing.get()); for(i = 0;i < data.first.len && SL_RESULT_SUCCESS == result;i++) { result = VCALL(bufferQueue,Enqueue)(data.first.buf + chunk_size*i, chunk_size); @@ -935,7 +927,7 @@ static ALCenum ALCopenslCapture_captureSamples(ALCopenslCapture *self, ALCvoid * /* Read the desired samples from the ring buffer then advance its read * pointer. */ - auto data = ll_ringbuffer_get_read_vector(self->mRing); + auto data = ll_ringbuffer_get_read_vector(self->mRing.get()); for(i = 0;i < samples;) { ALCuint rem = minu(samples - i, device->UpdateSize - self->mSplOffset); @@ -949,7 +941,7 @@ static ALCenum ALCopenslCapture_captureSamples(ALCopenslCapture *self, ALCvoid * /* Finished a chunk, reset the offset and advance the read pointer. */ self->mSplOffset = 0; - ll_ringbuffer_read_advance(self->mRing, 1); + ll_ringbuffer_read_advance(self->mRing.get(), 1); result = VCALL(bufferQueue,Enqueue)(data.first.buf, chunk_size); PRINTERR(result, "bufferQueue->Enqueue"); if(SL_RESULT_SUCCESS != result) break; @@ -978,7 +970,7 @@ static ALCenum ALCopenslCapture_captureSamples(ALCopenslCapture *self, ALCvoid * static ALCuint ALCopenslCapture_availableSamples(ALCopenslCapture *self) { ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - return ll_ringbuffer_read_space(self->mRing) * device->UpdateSize; + return ll_ringbuffer_read_space(self->mRing.get()) * device->UpdateSize; } diff --git a/Alc/backends/oss.cpp b/Alc/backends/oss.cpp index 110672c7..065f159a 100644 --- a/Alc/backends/oss.cpp +++ b/Alc/backends/oss.cpp @@ -501,7 +501,7 @@ void ALCplaybackOSS_stop(ALCplaybackOSS *self) struct ALCcaptureOSS final : public ALCbackend { int fd{-1}; - ll_ringbuffer_t *mRing{nullptr}; + RingBufferPtr mRing{nullptr}; std::atomic<ALenum> mKillNow{AL_TRUE}; std::thread mThread; @@ -537,8 +537,6 @@ void ALCcaptureOSS_Destruct(ALCcaptureOSS *self) close(self->fd); self->fd = -1; - ll_ringbuffer_free(self->mRing); - self->mRing = nullptr; ALCbackend_Destruct(STATIC_CAST(ALCbackend, self)); self->~ALCcaptureOSS(); } @@ -580,7 +578,7 @@ int ALCcaptureOSS_recordProc(ALCcaptureOSS *self) continue; } - auto vec = ll_ringbuffer_get_write_vector(self->mRing); + auto vec = ll_ringbuffer_get_write_vector(self->mRing.get()); if(vec.first.len > 0) { amt = read(self->fd, vec.first.buf, vec.first.len*frame_size); @@ -592,7 +590,7 @@ int ALCcaptureOSS_recordProc(ALCcaptureOSS *self) ALCcaptureOSS_unlock(self); break; } - ll_ringbuffer_write_advance(self->mRing, amt/frame_size); + ll_ringbuffer_write_advance(self->mRing.get(), amt/frame_size); } } @@ -698,7 +696,8 @@ ALCenum ALCcaptureOSS_open(ALCcaptureOSS *self, const ALCchar *name) return ALC_INVALID_VALUE; } - self->mRing = ll_ringbuffer_create(device->UpdateSize*device->NumUpdates, frameSize, false); + self->mRing.reset(ll_ringbuffer_create(device->UpdateSize*device->NumUpdates, frameSize, + false)); if(!self->mRing) { ERR("Ring buffer create failed\n"); @@ -739,13 +738,13 @@ void ALCcaptureOSS_stop(ALCcaptureOSS *self) ALCenum ALCcaptureOSS_captureSamples(ALCcaptureOSS *self, ALCvoid *buffer, ALCuint samples) { - ll_ringbuffer_read(self->mRing, static_cast<char*>(buffer), samples); + ll_ringbuffer_read(self->mRing.get(), static_cast<char*>(buffer), samples); return ALC_NO_ERROR; } ALCuint ALCcaptureOSS_availableSamples(ALCcaptureOSS *self) { - return ll_ringbuffer_read_space(self->mRing); + return ll_ringbuffer_read_space(self->mRing.get()); } } // namespace diff --git a/Alc/backends/portaudio.cpp b/Alc/backends/portaudio.cpp index 93384489..a89959b6 100644 --- a/Alc/backends/portaudio.cpp +++ b/Alc/backends/portaudio.cpp @@ -319,7 +319,7 @@ struct ALCportCapture final : public ALCbackend { PaStream *Stream{nullptr}; PaStreamParameters Params; - ll_ringbuffer_t *Ring{nullptr}; + RingBufferPtr Ring{nullptr}; }; int ALCportCapture_ReadCallback(const void *inputBuffer, void *outputBuffer, @@ -356,9 +356,6 @@ void ALCportCapture_Destruct(ALCportCapture *self) ERR("Error closing stream: %s\n", Pa_GetErrorText(err)); self->Stream = nullptr; - ll_ringbuffer_free(self->Ring); - self->Ring = nullptr; - ALCbackend_Destruct(STATIC_CAST(ALCbackend, self)); self->~ALCportCapture(); } @@ -369,10 +366,7 @@ int ALCportCapture_ReadCallback(const void *inputBuffer, void *UNUSED(outputBuff const PaStreamCallbackFlags UNUSED(statusFlags), void *userData) { ALCportCapture *self = static_cast<ALCportCapture*>(userData); - size_t writable = ll_ringbuffer_write_space(self->Ring); - - if(framesPerBuffer > writable) framesPerBuffer = writable; - ll_ringbuffer_write(self->Ring, inputBuffer, framesPerBuffer); + ll_ringbuffer_write(self->Ring.get(), inputBuffer, framesPerBuffer); return 0; } @@ -392,8 +386,8 @@ ALCenum ALCportCapture_open(ALCportCapture *self, const ALCchar *name) samples = maxu(samples, 100 * device->Frequency / 1000); frame_size = device->frameSizeFromFmt(); - self->Ring = ll_ringbuffer_create(samples, frame_size, false); - if(self->Ring == nullptr) return ALC_INVALID_VALUE; + self->Ring.reset(ll_ringbuffer_create(samples, frame_size, false)); + if(!self->Ring) return ALC_INVALID_VALUE; self->Params.device = -1; if(!ConfigValueInt(nullptr, "port", "capture", &self->Params.device) || @@ -462,12 +456,12 @@ void ALCportCapture_stop(ALCportCapture *self) ALCuint ALCportCapture_availableSamples(ALCportCapture *self) { - return ll_ringbuffer_read_space(self->Ring); + return ll_ringbuffer_read_space(self->Ring.get()); } ALCenum ALCportCapture_captureSamples(ALCportCapture *self, ALCvoid *buffer, ALCuint samples) { - ll_ringbuffer_read(self->Ring, buffer, samples); + ll_ringbuffer_read(self->Ring.get(), buffer, samples); return ALC_NO_ERROR; } diff --git a/Alc/backends/sndio.cpp b/Alc/backends/sndio.cpp index 9ebad671..25566490 100644 --- a/Alc/backends/sndio.cpp +++ b/Alc/backends/sndio.cpp @@ -279,7 +279,7 @@ static void SndioPlayback_stop(SndioPlayback *self) struct SndioCapture final : public ALCbackend { struct sio_hdl *sndHandle{nullptr}; - ll_ringbuffer_t *ring{nullptr}; + RingBufferPtr ring{nullptr}; std::atomic<ALenum> mKillNow{AL_TRUE}; std::thread mThread; @@ -316,9 +316,6 @@ static void SndioCapture_Destruct(SndioCapture *self) sio_close(self->sndHandle); self->sndHandle = nullptr; - ll_ringbuffer_free(self->ring); - self->ring = nullptr; - ALCbackend_Destruct(STATIC_CAST(ALCbackend, self)); self->~SndioCapture(); } @@ -339,7 +336,7 @@ static int SndioCapture_recordProc(SndioCapture *self) { size_t total, todo; - auto data = ll_ringbuffer_get_write_vector(self->ring); + auto data = ll_ringbuffer_get_write_vector(self->ring.get()); todo = data.first.len + data.second.len; if(todo == 0) { @@ -372,7 +369,7 @@ static int SndioCapture_recordProc(SndioCapture *self) data.first.len -= got; total += got; } - ll_ringbuffer_write_advance(self->ring, total / frameSize); + ll_ringbuffer_write_advance(self->ring.get(), total / frameSize); } return 0; @@ -468,7 +465,8 @@ static ALCenum SndioCapture_open(SndioCapture *self, const ALCchar *name) return ALC_INVALID_VALUE; } - self->ring = ll_ringbuffer_create(device->UpdateSize*device->NumUpdates, par.bps*par.rchan, 0); + self->ring.reset(ll_ringbuffer_create(device->UpdateSize*device->NumUpdates, + par.bps*par.rchan, false)); if(!self->ring) { ERR("Failed to allocate %u-byte ringbuffer\n", @@ -516,13 +514,13 @@ static void SndioCapture_stop(SndioCapture *self) static ALCenum SndioCapture_captureSamples(SndioCapture *self, void *buffer, ALCuint samples) { - ll_ringbuffer_read(self->ring, static_cast<char*>(buffer), samples); + ll_ringbuffer_read(self->ring.get(), static_cast<char*>(buffer), samples); return ALC_NO_ERROR; } static ALCuint SndioCapture_availableSamples(SndioCapture *self) { - return ll_ringbuffer_read_space(self->ring); + return ll_ringbuffer_read_space(self->ring.get()); } diff --git a/Alc/backends/wasapi.cpp b/Alc/backends/wasapi.cpp index 79e4af04..3f8cad23 100644 --- a/Alc/backends/wasapi.cpp +++ b/Alc/backends/wasapi.cpp @@ -1172,7 +1172,7 @@ struct ALCwasapiCapture final : public ALCbackend, WasapiProxy { ChannelConverter *mChannelConv{nullptr}; SampleConverter *mSampleConv{nullptr}; - ll_ringbuffer_t *mRing{nullptr}; + RingBufferPtr mRing{nullptr}; std::atomic<int> mKillNow{AL_TRUE}; std::thread mThread; @@ -1220,9 +1220,6 @@ void ALCwasapiCapture_Destruct(ALCwasapiCapture *self) CloseHandle(self->mNotifyEvent); self->mNotifyEvent = nullptr; - ll_ringbuffer_free(self->mRing); - self->mRing = nullptr; - DestroySampleConverter(&self->mSampleConv); DestroyChannelConverter(&self->mChannelConv); @@ -1275,7 +1272,7 @@ FORCE_ALIGN int ALCwasapiCapture_recordProc(ALCwasapiCapture *self) rdata = reinterpret_cast<BYTE*>(samples.data()); } - auto data = ll_ringbuffer_get_write_vector(self->mRing); + auto data = ll_ringbuffer_get_write_vector(self->mRing.get()); size_t dstframes; if(self->mSampleConv) @@ -1311,7 +1308,7 @@ FORCE_ALIGN int ALCwasapiCapture_recordProc(ALCwasapiCapture *self) dstframes = len1 + len2; } - ll_ringbuffer_write_advance(self->mRing, dstframes); + ll_ringbuffer_write_advance(self->mRing.get(), dstframes); hr = capture->ReleaseBuffer(numsamples); if(FAILED(hr)) ERR("Failed to release capture buffer: 0x%08lx\n", hr); @@ -1696,8 +1693,7 @@ HRESULT ALCwasapiCapture::resetProxy() } buffer_len = maxu(device->UpdateSize*device->NumUpdates, buffer_len); - ll_ringbuffer_free(mRing); - mRing = ll_ringbuffer_create(buffer_len, device->frameSizeFromFmt(), false); + mRing.reset(ll_ringbuffer_create(buffer_len, device->frameSizeFromFmt(), false)); if(!mRing) { ERR("Failed to allocate capture ring buffer\n"); @@ -1790,14 +1786,12 @@ void ALCwasapiCapture::stopProxy() ALuint ALCwasapiCapture_availableSamples(ALCwasapiCapture *self) { - return (ALuint)ll_ringbuffer_read_space(self->mRing); + return (ALuint)ll_ringbuffer_read_space(self->mRing.get()); } ALCenum ALCwasapiCapture_captureSamples(ALCwasapiCapture *self, ALCvoid *buffer, ALCuint samples) { - if(ALCwasapiCapture_availableSamples(self) < samples) - return ALC_INVALID_VALUE; - ll_ringbuffer_read(self->mRing, reinterpret_cast<char*>(buffer), samples); + ll_ringbuffer_read(self->mRing.get(), reinterpret_cast<char*>(buffer), samples); return ALC_NO_ERROR; } diff --git a/Alc/backends/winmm.cpp b/Alc/backends/winmm.cpp index 362b2e5e..38766869 100644 --- a/Alc/backends/winmm.cpp +++ b/Alc/backends/winmm.cpp @@ -401,7 +401,7 @@ struct ALCwinmmCapture final : public ALCbackend { HWAVEIN InHdl{nullptr}; - ll_ringbuffer_t *Ring{nullptr}; + RingBufferPtr Ring{nullptr}; WAVEFORMATEX Format{}; @@ -448,9 +448,6 @@ void ALCwinmmCapture_Destruct(ALCwinmmCapture *self) al_free(self->WaveBuffer[0].lpData); std::fill(self->WaveBuffer.begin(), self->WaveBuffer.end(), WAVEHDR{}); - ll_ringbuffer_free(self->Ring); - self->Ring = nullptr; - ALCbackend_Destruct(STATIC_CAST(ALCbackend, self)); self->~ALCwinmmCapture(); } @@ -497,7 +494,7 @@ int ALCwinmmCapture_captureProc(ALCwinmmCapture *self) WAVEHDR &waveHdr = self->WaveBuffer[widx]; widx = (widx+1) % self->WaveBuffer.size(); - ll_ringbuffer_write(self->Ring, waveHdr.lpData, + ll_ringbuffer_write(self->Ring.get(), waveHdr.lpData, waveHdr.dwBytesRecorded / self->Format.nBlockAlign ); self->Readable.fetch_sub(1, std::memory_order_acq_rel); @@ -585,7 +582,7 @@ ALCenum ALCwinmmCapture_open(ALCwinmmCapture *self, const ALCchar *deviceName) std::max<size_t>(device->UpdateSize*device->NumUpdates, BufferSize*self->WaveBuffer.size()) ); - self->Ring = ll_ringbuffer_create(CapturedDataSize, self->Format.nBlockAlign, false); + self->Ring.reset(ll_ringbuffer_create(CapturedDataSize, self->Format.nBlockAlign, false)); if(!self->Ring) return ALC_INVALID_VALUE; al_free(self->WaveBuffer[0].lpData); @@ -648,13 +645,13 @@ void ALCwinmmCapture_stop(ALCwinmmCapture *self) ALCenum ALCwinmmCapture_captureSamples(ALCwinmmCapture *self, ALCvoid *buffer, ALCuint samples) { - ll_ringbuffer_read(self->Ring, buffer, samples); + ll_ringbuffer_read(self->Ring.get(), buffer, samples); return ALC_NO_ERROR; } ALCuint ALCwinmmCapture_availableSamples(ALCwinmmCapture *self) { - return (ALCuint)ll_ringbuffer_read_space(self->Ring); + return (ALCuint)ll_ringbuffer_read_space(self->Ring.get()); } } // namespace diff --git a/Alc/ringbuffer.cpp b/Alc/ringbuffer.cpp index 5ee2616f..a298ff43 100644 --- a/Alc/ringbuffer.cpp +++ b/Alc/ringbuffer.cpp @@ -31,25 +31,9 @@ #include "compat.h" -/* NOTE: This lockless ringbuffer implementation is copied from JACK, extended - * to include an element size. Consequently, parameters and return values for a - * size or count is in 'elements', not bytes. Additionally, it only supports - * single-consumer/single-provider operation. */ -struct ll_ringbuffer { - std::atomic<size_t> write_ptr{0u}; - std::atomic<size_t> read_ptr{0u}; - size_t size{0u}; - size_t size_mask{0u}; - size_t elem_size{0u}; - - alignas(16) char buf[]; - - DEF_PLACE_NEWDEL() -}; - -ll_ringbuffer_t *ll_ringbuffer_create(size_t sz, size_t elem_sz, int limit_writes) +ll_ringbuffer *ll_ringbuffer_create(size_t sz, size_t elem_sz, int limit_writes) { - ll_ringbuffer_t *rb; + ll_ringbuffer *rb; size_t power_of_two = 0; if(sz > 0) @@ -75,12 +59,7 @@ ll_ringbuffer_t *ll_ringbuffer_create(size_t sz, size_t elem_sz, int limit_write return rb; } -void ll_ringbuffer_free(ll_ringbuffer_t *rb) -{ - delete rb; -} - -void ll_ringbuffer_reset(ll_ringbuffer_t *rb) +void ll_ringbuffer_reset(ll_ringbuffer *rb) { rb->write_ptr.store(0, std::memory_order_relaxed); rb->read_ptr.store(0, std::memory_order_relaxed); @@ -88,14 +67,14 @@ void ll_ringbuffer_reset(ll_ringbuffer_t *rb) } -size_t ll_ringbuffer_read_space(const ll_ringbuffer_t *rb) +size_t ll_ringbuffer_read_space(const ll_ringbuffer *rb) { size_t w = rb->write_ptr.load(std::memory_order_acquire); size_t r = rb->read_ptr.load(std::memory_order_acquire); return (w-r) & rb->size_mask; } -size_t ll_ringbuffer_write_space(const ll_ringbuffer_t *rb) +size_t ll_ringbuffer_write_space(const ll_ringbuffer *rb) { size_t w = rb->write_ptr.load(std::memory_order_acquire); size_t r = rb->read_ptr.load(std::memory_order_acquire); @@ -104,7 +83,7 @@ size_t ll_ringbuffer_write_space(const ll_ringbuffer_t *rb) } -size_t ll_ringbuffer_read(ll_ringbuffer_t *rb, void *dest, size_t cnt) +size_t ll_ringbuffer_read(ll_ringbuffer *rb, void *dest, size_t cnt) { size_t read_ptr; size_t free_cnt; @@ -143,7 +122,7 @@ size_t ll_ringbuffer_read(ll_ringbuffer_t *rb, void *dest, size_t cnt) return to_read; } -size_t ll_ringbuffer_peek(ll_ringbuffer_t *rb, void *dest, size_t cnt) +size_t ll_ringbuffer_peek(ll_ringbuffer *rb, void *dest, size_t cnt) { size_t free_cnt; size_t cnt2; @@ -180,7 +159,7 @@ size_t ll_ringbuffer_peek(ll_ringbuffer_t *rb, void *dest, size_t cnt) return to_read; } -size_t ll_ringbuffer_write(ll_ringbuffer_t *rb, const void *src, size_t cnt) +size_t ll_ringbuffer_write(ll_ringbuffer *rb, const void *src, size_t cnt) { size_t write_ptr; size_t free_cnt; @@ -220,18 +199,18 @@ size_t ll_ringbuffer_write(ll_ringbuffer_t *rb, const void *src, size_t cnt) } -void ll_ringbuffer_read_advance(ll_ringbuffer_t *rb, size_t cnt) +void ll_ringbuffer_read_advance(ll_ringbuffer *rb, size_t cnt) { rb->read_ptr.fetch_add(cnt, std::memory_order_acq_rel); } -void ll_ringbuffer_write_advance(ll_ringbuffer_t *rb, size_t cnt) +void ll_ringbuffer_write_advance(ll_ringbuffer *rb, size_t cnt) { rb->write_ptr.fetch_add(cnt, std::memory_order_acq_rel); } -ll_ringbuffer_data_pair ll_ringbuffer_get_read_vector(const ll_ringbuffer_t *rb) +ll_ringbuffer_data_pair ll_ringbuffer_get_read_vector(const ll_ringbuffer *rb) { ll_ringbuffer_data_pair ret; size_t free_cnt; @@ -265,7 +244,7 @@ ll_ringbuffer_data_pair ll_ringbuffer_get_read_vector(const ll_ringbuffer_t *rb) return ret; } -ll_ringbuffer_data_pair ll_ringbuffer_get_write_vector(const ll_ringbuffer_t *rb) +ll_ringbuffer_data_pair ll_ringbuffer_get_write_vector(const ll_ringbuffer *rb) { ll_ringbuffer_data_pair ret; size_t free_cnt; diff --git a/Alc/ringbuffer.h b/Alc/ringbuffer.h index cb2077f8..5111023e 100644 --- a/Alc/ringbuffer.h +++ b/Alc/ringbuffer.h @@ -3,19 +3,36 @@ #include <stddef.h> +#include <atomic> #include <memory> #include <utility> +#include "almalloc.h" + + +/* NOTE: This lockless ringbuffer implementation is copied from JACK, extended + * to include an element size. Consequently, parameters and return values for a + * size or count is in 'elements', not bytes. Additionally, it only supports + * single-consumer/single-provider operation. + */ +struct ll_ringbuffer { + std::atomic<size_t> write_ptr{0u}; + std::atomic<size_t> read_ptr{0u}; + size_t size{0u}; + size_t size_mask{0u}; + size_t elem_size{0u}; + + alignas(16) char buf[]; + + DEF_PLACE_NEWDEL() +}; -struct ll_ringbuffer; -using ll_ringbuffer_t = struct ll_ringbuffer; struct ll_ringbuffer_data { char *buf; size_t len; }; using ll_ringbuffer_data_pair = std::pair<ll_ringbuffer_data,ll_ringbuffer_data>; -using ll_ringbuffer_data_t = struct ll_ringbuffer_data; /** @@ -23,61 +40,55 @@ using ll_ringbuffer_data_t = struct ll_ringbuffer_data; * The number of elements is rounded up to the next power of two (even if it is * already a power of two, to ensure the requested amount can be written). */ -ll_ringbuffer_t *ll_ringbuffer_create(size_t sz, size_t elem_sz, int limit_writes); -/** Free all data associated with the ringbuffer `rb'. */ -void ll_ringbuffer_free(ll_ringbuffer_t *rb); +ll_ringbuffer *ll_ringbuffer_create(size_t sz, size_t elem_sz, int limit_writes); /** Reset the read and write pointers to zero. This is not thread safe. */ -void ll_ringbuffer_reset(ll_ringbuffer_t *rb); +void ll_ringbuffer_reset(ll_ringbuffer *rb); /** * The non-copying data reader. Returns two ringbuffer data pointers that hold * the current readable data at `rb'. If the readable data is in one segment * the second segment has zero length. */ -ll_ringbuffer_data_pair ll_ringbuffer_get_read_vector(const ll_ringbuffer_t *rb); +ll_ringbuffer_data_pair ll_ringbuffer_get_read_vector(const ll_ringbuffer *rb); /** * The non-copying data writer. Returns two ringbuffer data pointers that hold * the current writeable data at `rb'. If the writeable data is in one segment * the second segment has zero length. */ -ll_ringbuffer_data_pair ll_ringbuffer_get_write_vector(const ll_ringbuffer_t *rb); +ll_ringbuffer_data_pair ll_ringbuffer_get_write_vector(const ll_ringbuffer *rb); /** * Return the number of elements available for reading. This is the number of * elements in front of the read pointer and behind the write pointer. */ -size_t ll_ringbuffer_read_space(const ll_ringbuffer_t *rb); +size_t ll_ringbuffer_read_space(const ll_ringbuffer *rb); /** * The copying data reader. Copy at most `cnt' elements from `rb' to `dest'. * Returns the actual number of elements copied. */ -size_t ll_ringbuffer_read(ll_ringbuffer_t *rb, void *dest, size_t cnt); +size_t ll_ringbuffer_read(ll_ringbuffer *rb, void *dest, size_t cnt); /** * The copying data reader w/o read pointer advance. Copy at most `cnt' * elements from `rb' to `dest'. Returns the actual number of elements copied. */ -size_t ll_ringbuffer_peek(ll_ringbuffer_t *rb, void *dest, size_t cnt); +size_t ll_ringbuffer_peek(ll_ringbuffer *rb, void *dest, size_t cnt); /** Advance the read pointer `cnt' places. */ -void ll_ringbuffer_read_advance(ll_ringbuffer_t *rb, size_t cnt); +void ll_ringbuffer_read_advance(ll_ringbuffer *rb, size_t cnt); /** * Return the number of elements available for writing. This is the number of * elements in front of the write pointer and behind the read pointer. */ -size_t ll_ringbuffer_write_space(const ll_ringbuffer_t *rb); +size_t ll_ringbuffer_write_space(const ll_ringbuffer *rb); /** * The copying data writer. Copy at most `cnt' elements to `rb' from `src'. * Returns the actual number of elements copied. */ -size_t ll_ringbuffer_write(ll_ringbuffer_t *rb, const void *src, size_t cnt); +size_t ll_ringbuffer_write(ll_ringbuffer *rb, const void *src, size_t cnt); /** Advance the write pointer `cnt' places. */ -void ll_ringbuffer_write_advance(ll_ringbuffer_t *rb, size_t cnt); +void ll_ringbuffer_write_advance(ll_ringbuffer *rb, size_t cnt); -struct RingBufferDeleter { - void operator()(ll_ringbuffer_t *ring) const - { ll_ringbuffer_free(ring); } -}; -using RingBufferPtr = std::unique_ptr<ll_ringbuffer_t,RingBufferDeleter>; +using RingBufferPtr = std::unique_ptr<ll_ringbuffer>; #endif /* RINGBUFFER_H */ |