Commit Graph

200 Commits (22cd16bb463ee9083748f6337d11bb0d1f973223)

Author SHA1 Message Date
Christopher Snowhill bb11567948 [Audio Output] Change converter back to Obj-C
Change converter source file back from Objective-C++ to Objective-C.

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
2022-06-27 01:00:42 -07:00
Christopher Snowhill c489d7ca91 [Audio Output] Play last track and stop correctly
Play last track up until it actually ends, and stop on command.

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
2022-06-25 06:43:16 -07:00
Christopher Snowhill a1a084aabb [Audio Output] Fix serious deadlock issue
There was a serious deadlock issue. Now it is fixed. Whew.

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
2022-06-25 05:14:04 -07:00
Christopher Snowhill cca447ca5e [InputNode] Syntax code fix
This code was misformatted.

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
2022-06-25 05:13:57 -07:00
Christopher Snowhill d563617998 [Audio Output] Stop immediately, and fix deadlocks
Stop output when requested, except on natural completion of the last
track in the play queue. Also fix deadlocks with stopping and
restarting.

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
2022-06-24 19:14:48 -07:00
Christopher Snowhill dccb7f8b47 Replace Core Audio output with Core Media runtime
The output now uses AVSampleBufferAudioRenderer to play all formats, and
uses that to resample. It also supports Spatial Audio on macOS 12.0 or
newer. Note that there are some outstanding bugs with Spatial Audio
support. Namely that it appears to be limited to only 192 kHz at mono or
stereo, or 352800 Hz at surround configurations. This breaks DSD64
playback at stereo formats, as well as possibly other things. This is
entirely an Apple bug. I have reported it to Apple with reference code
FB10441301 for reference, in case anyone else wants to complain that it
isn't fixed.

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
2022-06-23 23:23:13 -07:00
Christopher Snowhill 1c36869e57 [Audio Threads] Remove unused code
This code turned out to be somewhat of a mistake to employ, so it's now
being removed, and shall not be re-added, as it doesn't really work.

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
2022-06-18 23:02:24 -07:00
Christopher Snowhill a2d8e0ec42 [Track Info] Add play count tabulation and display
Add play count data collection, including first seen times for every
file first added to the playlist. Data is indexed by album, artist, and
title, or by filename, whichever matches first. Add interfaces to
AppleScript automation definition as well.

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
2022-06-18 23:00:08 -07:00
Christopher Snowhill 4a269f05a1 [Audio Threads] Remove workgroup code
As it doesn't seem to work properly on Intel machines, anyway. It just
leads to pointless crashes, and doesn't seem to serve any purpose.

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
2022-06-18 15:43:40 -07:00
Christopher Snowhill 3156aad9e1 [Audio Threads] Restrict workgroup use to macOS 12
Restrict the use of workgroup joining and workgroup intervals to macOS
Monterey or newer, as it seems the way I use it, it's completely broken
on macOS Big Sur, which was the original minimum target for the API.

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
2022-06-17 22:39:00 -07:00
Christopher Snowhill fa177fe96c [Audio Threads] Make work interval name unique
Work interval names should be unique. Apparently they are deduplicated
based on their names?

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
2022-06-17 18:04:42 -07:00
Christopher Snowhill e334d8a017 [Audio Threads] Apply changes to workgroup handler
Apply changes to exit the thread if workgroup initialization or joining
fails, instead of attempting to continue executing the thread.

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
2022-06-17 18:02:32 -07:00
Christopher Snowhill dad2dbf236 [Audio Threads] Add extra guard to workgroup exit
Add an extra step to the workgroup exit call, so that it only calls to
leave if the join token is valid, or at least initialized.

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
2022-06-17 17:00:59 -07:00
Christopher Snowhill 7bc49ccb80 [Event Handler] Fix observers for reused classes
Fix class handling so it cleans up observers if the InputNode is reused.

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
2022-06-16 18:16:09 -07:00
Christopher Snowhill e9230a080c [Audio Threads] Change workgroup code for safety
The changes include no longer leaving the workgroup for seeking or for
converter format changes, and also still leaving the workgroup on thread
termination if there was an error with intervals starting or finishing.

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
2022-06-15 21:44:03 -07:00
Christopher Snowhill 8db2e41049 [Event Handling] Add context to all observers
Add context field to all observers that support it, in case it's useful.

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
2022-06-15 16:47:43 -07:00
Christopher Snowhill 6825d15f68 [HRIR Filter] Employ impulse cache
An impulse cache reduces any glitching from format channel count changes
to near insignificant levels, resulting in a more pleasant experience
when there are different mixed formats playing, or even a file which
changes format mid-playback.

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
2022-06-12 22:21:01 -07:00
Christopher Snowhill 120a93465e [Metadata Handling] Fix dynamic info updates
Ensure that dynamic info updates, even on static files, only update the
exact track they apply to, by atomically assigning the userInfo property
before opening the decoder, so that callbacks to the player indicate the
correct track and don't assume it's the one that's currently visibly
playing. Fixes start of track metadata notifications from overwriting
the previously playing track.

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
2022-06-12 19:43:41 -07:00
Christopher Snowhill 6c733762d3 [HRIR Filter] Add safety margin for DFT
DFT float happens to clobber one extra sample on forward translate, so
allocate one extra for every complex buffer.

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
2022-06-11 03:32:38 -07:00
Christopher Snowhill 040a61e1ed [HRIR Filter] Replace implementation with vDSP
Work back to a vDSP implementation, this time using overlap-save instead
of overlap-add, also accumulating the results as complex values, only
inversing them once at the end, and finally, replacing the FFT method
with the newer DFT API.

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
2022-06-11 02:25:40 -07:00
Christopher Snowhill ef2ba385f2 [Audio Threads] Clear workgroup token on exit
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>
2022-06-10 16:42:33 -07:00
Christopher Snowhill 22a41e71d3 [Audio Threads] Add further safety gating on error
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>
2022-06-10 15:20:07 -07:00
Christopher Snowhill fe82b5ed65 [DSD] Reduce volume level of decimator output
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>
2022-06-10 02:14:04 -07:00
Christopher Snowhill 4537a72275 [DSD] Add pure downsampling path, disabled
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>
2022-06-10 02:13:10 -07:00
Christopher Snowhill 6bd0bf1dc5 [Audio Threads] Set realtime priority on old OS
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>
2022-06-09 18:53:58 -07:00
Christopher Snowhill 7813712df3 [Audio Threads] Correctly set real time priority
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>
2022-06-09 18:15:44 -07:00
Christopher Snowhill 91898e9e77 [Audio Threads] Change workgroup system again
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>
2022-06-09 01:38:30 -07:00
Christopher Snowhill 6179b304d0 [Audio Threads] Join output device workgroup
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>
2022-06-09 00:27:55 -07:00
Christopher Snowhill c208f60da4 [HRIR Convolver] Rewrite to use PFFFT float
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>
2022-06-06 08:18:33 -07:00
Christopher Snowhill 18af8a06df [Output] [Downmixer] Optimize a bit
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>
2022-06-06 08:16:27 -07:00
Christopher Snowhill 50342891af [Convolver] Normalize HRTF impulse when resampling
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>
2022-05-30 01:39:12 -07:00
Christopher Snowhill 5622e92899 Resampler: Fix gapless output
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>
2022-03-05 20:40:18 -08:00
Christopher Snowhill 6dccaa4d7f Fixes starting playback on short files
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>
2022-03-05 15:53:47 -08:00
Christopher Snowhill 777ab28d6a Replaced libsoxr with r8brain free source
Replaced the free SoX resampler with the r8brain resampler source, which
is also free.

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
2022-03-04 02:07:38 -08:00
Christopher Snowhill 4906c38827 Align all use of Accelerate vDSP functions
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>
2022-02-15 22:53:09 -08:00
Christopher Snowhill 25077277b3 Add bad sample cleaner for debugging
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>
2022-02-15 22:48:47 -08:00
Christopher Snowhill 96f2a382ee DSD gaplessness, part 3, mildly pointless
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>
2022-02-15 02:29:06 -08:00
Christopher Snowhill bec01b675a DSD gaplessness, part 2
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>
2022-02-15 02:11:53 -08:00
Christopher Snowhill 4b0f6b381f Fix DSD gaplessness handling
DSD files should be properly gapless now.

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
2022-02-15 02:03:06 -08:00
Christopher Snowhill b8a98e301e Metadata loading: Correctly merge over empty tags
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>
2022-02-14 20:02:18 -08:00
Christopher Snowhill 6d09b72c1d Dynamic info now pushes to the correct track
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
2022-02-12 07:29:02 -08:00
Christopher Snowhill c39b7ee96a Converter: Smarter, if less portable, endian swap
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>
2022-02-12 00:38:08 -08:00
Christopher Snowhill 5f68131437 Converter: One minor change to double to float
Use Accelerate for this, too.

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
2022-02-12 00:03:25 -08:00
Christopher Snowhill 6b148fef11 Channel Mixer: Rewrite upmixing, changed HRIR
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>
2022-02-11 23:51:41 -08:00
Christopher Snowhill 3711999112 Cog Audio: Allocate maximum needed audio memory
The chunk could be any format, up to floating point double samples, and
up to 18 channels.

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
2022-02-11 13:50:26 -08:00
Christopher Snowhill 7f8c19799d Fix a very serious error resampling short files
Files that are so short that they need both pre- and post-extrapolation
at the same time.

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
2022-02-11 07:10:31 -08:00
Christopher Snowhill 0b33fe6dea Don't count output buffering for queue hold
This would count the output duration for every file buffered, rather
than only once.

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
2022-02-11 06:50:58 -08:00
Christopher Snowhill 5ff1f95481 Add decoder open error indicator
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>
2022-02-10 02:15:48 -08:00
Christopher Snowhill df63726128 Track properties take priority over metadata read from tag readers
This allows inputs to override things with self-read tags and such, such
as ReplayGain tags.

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
2022-02-09 21:26:17 -08:00
Christopher Snowhill b1a98139cb Cog Audio: Fix generic upmixer mode
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>
2022-02-09 15:16:19 -08:00