Use unique_ptrs for a few more types to avoid explicit free calls.
Move ThreadMainloop::wait to the unique_lock wrapper that's holding the lock.
Since the mainloop acts as both a lock and condition_variable, passing the lock
to the wait method makes no sense. Also have it optionally take a predicate
functor to dictate when to stop waiting.
The parser thread could be waiting on the threads to join after queueing all
packets, so it wouldn't see mQuit to flush the queue. So make a stop method
that forces a flush when setting mQuit.
This isn't great since it can fail when PipeWire is handling audio but no
devices are available at initialization, causing the Pulseaudio or ALSA backend
to be selected instead. Future versions of PipeWire are expected to have a
better way to detect if it's handling audio, but for now this is better than
nothing.
A config option is available for users to have the PipeWire backend be usable
even with no devices at initialization, just in case.
Directly mixing a non-UHJ stereo signal into a UHJ stereo signal results in a
non-UHJ stereo signal. Such a mix can't be properly decoded anymore.
An option can probably be added for users that intend to listen to UHJ output
undecoded and let a stereo sound come through as-is on their speakers, but it
probably shouldn't be the default for cases where the output may be decoded
back.
MinGW-w64 generates bad code when accessing extern thread_local objects.
Wrapper functions are used to ensure it only accesses them from the same place
they're defined. This unfortunately adds a bit of overhead for what should be a
relatively simple thing.
These functions are inlined for non-MinGW targets, avoiding the overhead on
non-affected targets.
It can be initialized once with the device's speaker distance since it won't
change in between resets, then copied into the voice where it can be adjusted
as needed.
It's not available as an AL buffer format (yet) since I'm not sure how to
expose it. Internally it seems fine as a separate channel configuration, but
because OpenAL combines the channel configuration and sample type, a flag may
work better there.
FlexArray would be better since it's not likely to use much memory for the
array, but the std::unique_ptr makes BFormatDec a non-standard layout, causing
GCC and Clang to complain.
This attempts to correct for the differences needed for 2-channel UHJ's shelf
filters given the output shelf filters. It's far from ideal, but better than
nothing.
a.k.a. Stereo Enhance. A common feature of UHJ decoders to take a plain
stereo signal and generate a B-Format signal with variable width control,
widening (or narrowing) the soundfield while maintaining a sharp central
image.
The extended precision of the encoder's 0.6512*X term was guesswork, with no
real basis for it. Switch back to the original value until something better
actually comes up. Also updates the decoder to account for the change in the
encoder.