aboutsummaryrefslogtreecommitdiffstats
path: root/alc
diff options
context:
space:
mode:
Diffstat (limited to 'alc')
-rw-r--r--alc/backends/jack.cpp98
1 files changed, 48 insertions, 50 deletions
diff --git a/alc/backends/jack.cpp b/alc/backends/jack.cpp
index 9ec66cfe..485225e4 100644
--- a/alc/backends/jack.cpp
+++ b/alc/backends/jack.cpp
@@ -169,6 +169,7 @@ struct JackPlayback final : public BackendBase {
jack_client_t *mClient{nullptr};
jack_port_t *mPort[MAX_OUTPUT_CHANNELS]{};
+ std::atomic<bool> mPlaying{false};
RingBufferPtr mRing;
al::semaphore mSem;
@@ -196,68 +197,63 @@ JackPlayback::~JackPlayback()
int JackPlayback::process(jack_nframes_t numframes) noexcept
{
jack_default_audio_sample_t *out[MAX_OUTPUT_CHANNELS];
- ALsizei numchans{0};
+ size_t numchans{0};
for(auto port : mPort)
{
if(!port) break;
out[numchans++] = static_cast<float*>(jack_port_get_buffer(port, numframes));
}
- auto data = mRing->getReadVector();
- jack_nframes_t todo{minu(numframes, static_cast<ALuint>(data.first.len))};
- std::transform(out, out+numchans, out,
- [&data,numchans,todo](ALfloat *outbuf) -> ALfloat*
+ jack_nframes_t total{0};
+ if LIKELY(mPlaying.load(std::memory_order_acquire))
+ {
+ auto data = mRing->getReadVector();
+ jack_nframes_t todo{minu(numframes, static_cast<ALuint>(data.first.len))};
+ auto write_first = [&data,numchans,todo](float *outbuf) -> float*
+ {
+ const float *RESTRICT in = reinterpret_cast<float*>(data.first.buf);
+ auto deinterlace_input = [&in,numchans]() noexcept -> float
+ {
+ float ret{*in};
+ in += numchans;
+ return ret;
+ };
+ std::generate_n(outbuf, todo, deinterlace_input);
+ data.first.buf += sizeof(float);
+ return outbuf + todo;
+ };
+ std::transform(out, out+numchans, out, write_first);
+ total += todo;
+
+ todo = minu(numframes-total, static_cast<ALuint>(data.second.len));
+ if(todo > 0)
{
- const ALfloat *RESTRICT in = reinterpret_cast<ALfloat*>(data.first.buf);
- std::generate_n(outbuf, todo,
- [&in,numchans]() noexcept -> ALfloat
+ auto write_second = [&data,numchans,todo](float *outbuf) -> float*
+ {
+ const float *RESTRICT in = reinterpret_cast<float*>(data.second.buf);
+ auto deinterlace_input = [&in,numchans]() noexcept -> float
{
- ALfloat ret{*in};
+ float ret{*in};
in += numchans;
return ret;
- }
- );
- data.first.buf += sizeof(ALfloat);
- return outbuf + todo;
+ };
+ std::generate_n(outbuf, todo, deinterlace_input);
+ data.second.buf += sizeof(float);
+ return outbuf + todo;
+ };
+ std::transform(out, out+numchans, out, write_second);
+ total += todo;
}
- );
- jack_nframes_t total{todo};
- todo = minu(numframes-total, static_cast<ALuint>(data.second.len));
- if(todo > 0)
- {
- std::transform(out, out+numchans, out,
- [&data,numchans,todo](ALfloat *outbuf) -> ALfloat*
- {
- const ALfloat *RESTRICT in = reinterpret_cast<ALfloat*>(data.second.buf);
- std::generate_n(outbuf, todo,
- [&in,numchans]() noexcept -> ALfloat
- {
- ALfloat ret{*in};
- in += numchans;
- return ret;
- }
- );
- data.second.buf += sizeof(ALfloat);
- return outbuf + todo;
- }
- );
- total += todo;
+ mRing->readAdvance(total);
+ mSem.post();
}
- mRing->readAdvance(total);
- mSem.post();
-
if(numframes > total)
{
- todo = numframes-total;
- std::transform(out, out+numchans, out,
- [todo](ALfloat *outbuf) -> ALfloat*
- {
- std::fill_n(outbuf, todo, 0.0f);
- return outbuf + todo;
- }
- );
+ jack_nframes_t todo{numframes - total};
+ auto clear_buf = [todo](ALfloat *outbuf) -> void { std::fill_n(outbuf, todo, 0.0f); };
+ std::for_each(out, out+numchans, clear_buf);
}
return 0;
@@ -318,9 +314,11 @@ void JackPlayback::open(const ALCchar *name)
if((status&JackNameNotUnique))
{
client_name = jack_get_client_name(mClient);
- TRACE("Client name not unique, got `%s' instead\n", client_name);
+ TRACE("Client name not unique, got '%s' instead\n", client_name);
}
+ jack_set_process_callback(mClient, &JackPlayback::processC, this);
+
mDevice->DeviceName = name;
}
@@ -429,8 +427,8 @@ bool JackPlayback::start()
mRing = nullptr;
mRing = RingBuffer::Create(bufsize, mDevice->frameSizeFromFmt(), true);
- jack_set_process_callback(mClient, &JackPlayback::processC, this);
try {
+ mPlaying.store(true, std::memory_order_release);
mKillNow.store(false, std::memory_order_release);
mThread = std::thread{std::mem_fn(&JackPlayback::mixerProc), this};
return true;
@@ -440,8 +438,8 @@ bool JackPlayback::start()
}
catch(...) {
}
- jack_set_process_callback(mClient, nullptr, nullptr);
jack_deactivate(mClient);
+ mPlaying.store(false, std::memory_order_release);
return false;
}
@@ -454,7 +452,7 @@ void JackPlayback::stop()
mThread.join();
jack_deactivate(mClient);
- jack_set_process_callback(mClient, nullptr, nullptr);
+ mPlaying.store(false, std::memory_order_release);
}