From e39038317623c6282c3fd5685fcceaf3cc3137c7 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 10 Aug 2024 01:44:49 -0700 Subject: [PATCH] Support non-float samples for uninterleaved output --- alc/alu.cpp | 34 ++++++++++++++++++++++++++++------ alc/backends/jack.cpp | 10 +++++----- alc/backends/pipewire.cpp | 4 ++-- alc/backends/wasapi.cpp | 18 +++++++++--------- core/device.h | 2 +- 5 files changed, 45 insertions(+), 23 deletions(-) diff --git a/alc/alu.cpp b/alc/alu.cpp index 644974da41..557ac0d8a9 100644 --- a/alc/alu.cpp +++ b/alc/alu.cpp @@ -2174,6 +2174,22 @@ void Write(const al::span InBuffer, void *OutBuffer, cons } } +template +void Write(const al::span InBuffer, al::span OutBuffers, + const size_t Offset, const size_t SamplesToDo) +{ + ASSUME(SamplesToDo > 0); + + auto srcbuf = InBuffer.cbegin(); + for(auto *dstbuf : OutBuffers) + { + const auto src = al::span{*srcbuf}.first(SamplesToDo); + const auto dst = al::span{static_cast(dstbuf), Offset+SamplesToDo}.subspan(Offset); + std::transform(src.cbegin(), src.end(), dst.begin(), SampleConv); + ++srcbuf; + } +} + } // namespace uint DeviceBase::renderSamples(const uint numSamples) @@ -2222,7 +2238,7 @@ uint DeviceBase::renderSamples(const uint numSamples) return samplesToDo; } -void DeviceBase::renderSamples(const al::span outBuffers, const uint numSamples) +void DeviceBase::renderSamples(const al::span outBuffers, const uint numSamples) { FPUCtl mixer_mode{}; uint total{0}; @@ -2230,13 +2246,19 @@ void DeviceBase::renderSamples(const al::span outBuffers, const uint num { const uint samplesToDo{renderSamples(todo)}; - auto srcbuf = RealOut.Buffer.cbegin(); - for(auto *dstbuf : outBuffers) + switch(FmtType) { - const auto dst = al::span{dstbuf, numSamples}.subspan(total); - std::copy_n(srcbuf->cbegin(), samplesToDo, dst.begin()); - ++srcbuf; +#define HANDLE_WRITE(T) case T: \ + Write>(RealOut.Buffer, outBuffers, total, samplesToDo); break; + HANDLE_WRITE(DevFmtByte) + HANDLE_WRITE(DevFmtUByte) + HANDLE_WRITE(DevFmtShort) + HANDLE_WRITE(DevFmtUShort) + HANDLE_WRITE(DevFmtInt) + HANDLE_WRITE(DevFmtUInt) + HANDLE_WRITE(DevFmtFloat) } +#undef HANDLE_WRITE total += samplesToDo; } diff --git a/alc/backends/jack.cpp b/alc/backends/jack.cpp index 39cfeb39cd..d8c567c59b 100644 --- a/alc/backends/jack.cpp +++ b/alc/backends/jack.cpp @@ -329,13 +329,13 @@ JackPlayback::~JackPlayback() int JackPlayback::processRt(jack_nframes_t numframes) noexcept { - auto outptrs = std::array{}; + auto outptrs = std::array{}; auto numchans = size_t{0}; for(auto port : mPort) { if(!port || numchans == mDevice->RealOut.Buffer.size()) break; - outptrs[numchans++] = static_cast(jack_port_get_buffer(port, numframes)); + outptrs[numchans++] = jack_port_get_buffer(port, numframes); } const auto dst = al::span{outptrs}.first(numchans); @@ -343,8 +343,8 @@ int JackPlayback::processRt(jack_nframes_t numframes) noexcept mDevice->renderSamples(dst, static_cast(numframes)); else { - std::for_each(dst.begin(), dst.end(), [numframes](float *outbuf) -> void - { std::fill_n(outbuf, numframes, 0.0f); }); + std::for_each(dst.begin(), dst.end(), [numframes](void *outbuf) -> void + { std::fill_n(static_cast(outbuf), numframes, 0.0f); }); } return 0; @@ -416,7 +416,7 @@ int JackPlayback::mixerProc() const auto update_size = uint{mDevice->UpdateSize}; const auto num_channels = size_t{mDevice->channelsFromFmt()}; - auto outptrs = std::vector(num_channels); + auto outptrs = std::vector(num_channels); while(!mKillNow.load(std::memory_order_acquire) && mDevice->Connected.load(std::memory_order_acquire)) diff --git a/alc/backends/pipewire.cpp b/alc/backends/pipewire.cpp index 23589dc6a0..5d41a8e1aa 100644 --- a/alc/backends/pipewire.cpp +++ b/alc/backends/pipewire.cpp @@ -1432,7 +1432,7 @@ class PipeWirePlayback final : public BackendBase { PwStreamPtr mStream; spa_hook mStreamListener{}; spa_io_rate_match *mRateMatch{}; - std::vector mChannelPtrs; + std::vector mChannelPtrs; static constexpr pw_stream_events CreateEvents() { @@ -1503,7 +1503,7 @@ void PipeWirePlayback::outputCallback() noexcept for(const auto &data : datas) { length = std::min(length, data.maxsize/uint{sizeof(float)}); - *chanptr_end = static_cast(data.data); + *chanptr_end = data.data; ++chanptr_end; data.chunk->offset = 0; diff --git a/alc/backends/wasapi.cpp b/alc/backends/wasapi.cpp index d1994b9d87..0e51996b7c 100644 --- a/alc/backends/wasapi.cpp +++ b/alc/backends/wasapi.cpp @@ -1253,8 +1253,8 @@ FORCE_ALIGN int WasapiPlayback::mixerSpatialProc() althrd_setname(GetMixerThreadName()); std::vector> channels; - std::vector buffers; - std::vector resbuffers; + std::vector buffers; + std::vector resbuffers; std::vector tmpbuffers; /* TODO: Set mPadding appropriately. There doesn't seem to be a way to @@ -1304,7 +1304,7 @@ FORCE_ALIGN int WasapiPlayback::mixerSpatialProc() auto bufptr = mResampleBuffer.begin(); for(size_t i{0};i < tmpbuffers.size();++i) { - resbuffers[i] = reinterpret_cast(al::to_address(bufptr)); + resbuffers[i] = al::to_address(bufptr); bufptr += ptrdiff_t(mDevice->UpdateSize*sizeof(float)); } } @@ -1314,12 +1314,12 @@ FORCE_ALIGN int WasapiPlayback::mixerSpatialProc() * update, unfortunately. */ std::transform(channels.cbegin(), channels.cend(), buffers.begin(), - [](const ComPtr &obj) -> float* + [](const ComPtr &obj) -> void* { - BYTE *buffer{}; - UINT32 size{}; + auto buffer = LPBYTE{}; + auto size = UINT32{}; obj->GetBuffer(&buffer, &size); - return reinterpret_cast(buffer); + return buffer; }); if(!mResampler) @@ -1337,9 +1337,9 @@ FORCE_ALIGN int WasapiPlayback::mixerSpatialProc() } const uint got{mResampler->convertPlanar(tmpbuffers.data(), &mBufferFilled, - reinterpret_cast(buffers.data()), framesToDo-pos)}; + buffers.data(), framesToDo-pos)}; for(auto &buf : buffers) - buf += got; /* NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) */ + buf = static_cast(buf) + got; /* NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) */ pos += got; } } diff --git a/core/device.h b/core/device.h index c5aef0e6e9..85f3cf478f 100644 --- a/core/device.h +++ b/core/device.h @@ -350,7 +350,7 @@ struct SIMDALIGN DeviceBase { inline void postProcess(const std::size_t SamplesToDo) { if(PostProcess) LIKELY (this->*PostProcess)(SamplesToDo); } - void renderSamples(const al::span outBuffers, const uint numSamples); + void renderSamples(const al::span outBuffers, const uint numSamples); void renderSamples(void *outBuffer, const uint numSamples, const std::size_t frameStep); /* Caller must lock the device state, and the mixer must not be running. */