When leaving the workgroup, clear the token, as the join call requires
the token to be uninitialized.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Errors should stop all attempts to further use the audio thread priority
code, so there won't be debug breakpoints called on older OSes.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
As the decimator has shown to be twice as loud as it should be, the
volume should be reduced by half when converting DSD to PCM with it.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Pure downsampling is slower, but may or may not be more accurate. Though
probably not worth it. It did help me realize a minor error, though.
The decimator's volume is twice as loud as it should be.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Set baseline real-time priority for audio threads even on old macOS,
since that API is available there. Only set it once, and do not attempt
again if it fails, only once per thread.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
I'm not sure about macOS Ventura, but stable releases of macOS, at
least on Intel, require that threads joining Audio Interval
workgroups already be set to run as real-time before joining. Not
doing this results in an uncaught exception and a crash.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Now it allocates audio workgroups per thread, using work slices like the
Apple documentation describes for asynchronous threads.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
On Big Sur or newer, it is possible to join the audio threads to the
same OS workgroup as the audio output device, improving response.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Replace overlap-add vDSP/Accelerate implementation with a faster PFFFT
overlap-save implementation, using fewer FFT steps as well.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Rewrite some of the output and a lot of the downmixer to use Accelerate
framework instead of dumb for loops.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
When resampling the impulse according to the playback rate, it becomes
necessary to normalize the resulting impulse by the inverse of the
sample ratio, as resampling adds more or less loudness by virtue of
interpolating samples.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The resampler wasn't being given enough room to flush its final output,
so a function was added to determine the current output latency, and
more sample data is requested, allowing the full output flush to occur.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
These two changes fix playback issues with either starting in the middle
of the playlist on a really short file terminating immediately instead
of queueing more files (InputNode.m), and issues with starting playback
at all on the end of a playlist on a short file. (OutputCoreAudio.m)
Fixes#246
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
vDSP functions expect their input and output pointers to be aligned to
an even four values. Correct this by aligning all pointers. The
allocated buffers used for one parameter should already be aligned
somewhat, but align the incremented positions used on some of them so
that the vDSP functions don't misbehave. Also align the volume scaler
input by doing scalar math until the pointer is aligned prior to calling
vDSP_vsmul. Also, change 16-bit and 32-bit scale to use vsdiv instead of
vsmul with a really small number already divided into one.
Fixes the test vectors that were sent in extrapolating incorrectly due
to their final blocks having uneven sample counts, resulting in
unaligned pointers.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
A bad sample scanner and cleaner will point out in the log whenever a
bad sample, such as infinity, or Not a Number, or even huge values over
±2.0, in case some piece of code, or a decoder, or even a bad file, has
taken over the output.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
In the rare event that we're somehow playing decimated DSD at full
sample rate instead of resampling, only the start needs to be skipped,
and the end needs the input to the decimator padded to flush it, but
nothing needs to be truncated from the end of the output in that case.
Still, mostly pointless, since next to nobody will be outputting 384 kHz
from their Macs, in any case, much less unprocessed DSD.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
We should be extrapolating right over top of the DSD decimator latency,
rather than in front of it. Yeah, that'll do.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Metadata versus properties merging, correctly merge over empty fields if
they are assigned with empty strings or zeroed numbers, instead of only
merging over completely missing fields.
Fixes emailed bug, CUE Sheet metadata reading, primarily.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
For big endian sample formats, endianness can be swapped using Clang
specific byte swap functions, which are present in all supported
versions of Xcode.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Simple upmixing algorithms now use Accelerate framework functions
instead of complex loops, and the HRIR filter now supports forcing
stereo output to any channel output configuration that has at least
front stereo speakers.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
When decoder is redirected to the internal silence decoder, show an icon
on the playlist indicating a playback error.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This resulted in horrible things, the generic N to N upmixer was leaving
unmapped channels as uninitialized memory. This fixes horrible things
happening for people with interfaces with more channels than the source
file, frequently when the source file is stereo, or if the file is mono
and a center channel is present.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
_mm_malloc and _mm_free are apparently based on intrinsic functions,
and only exist on Intel or older macOS targets. So removing them in
favor of posix_memalign.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Now the output is restarted on the current file at the current position
if the output format has changed. This should resolve the issue finally.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This was buggy as hell, and resulted in errors. Now the user should
restart playback if they change output device formats.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Sample format can now change dynamically at play time, and the player
will resample it as necessary, extrapolating edges between changes to
reduce the potential for gaps.
Currently supported formats for this:
- FLAC
- Ogg Vorbis
- Any format supported by FFmpeg, such as MP3 or AAC
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The ChunkList wasn't clearing the remover entered flag when the chain
was empty. Now it does, so it will shut down correctly.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Code ordering was wrong, it was writing the output samples repeatedly
for each input speaker, now it will only write them once.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
By applying copious amounts of autorelease pools, memory is freed in a
timely manner. Prior to this, buffer objects were freed, but not being
released, and thus accumulating in memory indefinitely, as the original
threads and functions had autorelease pools that scoped the entire
thread, rather than individual function blocks that utilized the new
buffering system. This fixes memory growth caused by playback.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This implements the basic output and mixing support for channel config
bits, optionally set by the input plugin.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
The volume should have been twice what it was, because I got this scale
wrong. The correct scale for Accelerate inverse FFT is 1/4 per sample,
not 1/8 like I accidentally misread while rewriting a convolver for the
umpteenth time from scratch.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Rewrite attempt number two. Now using array lists of audio chunks, with
each chunk having its format and optionally losslessness stashed along
with it. This replaces the old virtual ring buffer method. As a result
of this, the HRIR toggle now works instantaneously.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
After all this rewriting, down or upmixing the audio is now handled with
the lowest latency possible, meaning that toggling the HRIR option now
takes effect immediately.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
Flush the resampler when the source file terminates, so that it outputs
delayed samples properly. This fixes gapless decoding of resampled
files.
Signed-off-by: Christopher Snowhill <kode54@gmail.com>