Audio/HRTF: Make head tracking optional, add reset button
Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This commit is contained in:
parent
160c7e43b7
commit
ae71a6a2bc
10 changed files with 115 additions and 9 deletions
|
@ -98,7 +98,9 @@ NSString *CogPlaybackDidStopNotificiation = @"CogPlaybackDidStopNotificiation";
|
|||
@"GraphicEQpreset": @(-1),
|
||||
@"GraphicEQtrackgenre": @(NO),
|
||||
@"volumeLimit": @(YES),
|
||||
@"headphoneVirtualization": @(NO) };
|
||||
@"enableHrtf": @(NO),
|
||||
@"enableHeadTracking": @(NO)
|
||||
};
|
||||
|
||||
[[NSUserDefaults standardUserDefaults] registerDefaults:defaultsDictionary];
|
||||
}
|
||||
|
|
|
@ -75,6 +75,9 @@ using std::atomic_long;
|
|||
BOOL eqEnabled;
|
||||
BOOL eqInitialized;
|
||||
|
||||
BOOL enableHeadTracking;
|
||||
BOOL lastEnableHeadTracking;
|
||||
|
||||
BOOL streamFormatStarted;
|
||||
BOOL streamFormatChanged;
|
||||
|
||||
|
@ -84,6 +87,7 @@ using std::atomic_long;
|
|||
BOOL currentdevicelistenerapplied;
|
||||
BOOL devicealivelistenerapplied;
|
||||
BOOL observersapplied;
|
||||
BOOL htlistenerapplied;
|
||||
BOOL outputdevicechanged;
|
||||
|
||||
float volume;
|
||||
|
@ -182,6 +186,7 @@ using std::atomic_long;
|
|||
- (void)sustainHDCD;
|
||||
|
||||
- (void)reportMotion:(simd_float4x4)matrix;
|
||||
- (void)resetReferencePosition;
|
||||
|
||||
- (void)setPitch:(double)p;
|
||||
- (void)setTempo:(double)t;
|
||||
|
|
|
@ -31,6 +31,8 @@ extern void scale_by_volume(float *buffer, size_t count, float volume);
|
|||
|
||||
static NSString *CogPlaybackDidBeginNotificiation = @"CogPlaybackDidBeginNotificiation";
|
||||
|
||||
static NSString *CogPlaybackDidResetHeadTracking = @"CogPlaybackDigResetHeadTracking";
|
||||
|
||||
#define tts ((RubberBandState)ts)
|
||||
|
||||
simd_float4x4 convertMatrix(CMRotationMatrix r) {
|
||||
|
@ -394,8 +396,10 @@ current_device_listener(AudioObjectID inObjectID, UInt32 inNumberAddresses, cons
|
|||
} else if([keyPath isEqualToString:@"values.eqPreamp"]) {
|
||||
float preamp = [[[NSUserDefaultsController sharedUserDefaultsController] defaults] floatForKey:@"eqPreamp"];
|
||||
eqPreamp = pow(10.0, preamp / 20.0);
|
||||
} else if([keyPath isEqualToString:@"values.enableHrtf"]) {
|
||||
} else if([keyPath isEqualToString:@"values.enableHrtf"] ||
|
||||
[keyPath isEqualToString:@"values.enableHeadTracking"]) {
|
||||
enableHrtf = [[[NSUserDefaultsController sharedUserDefaultsController] defaults] boolForKey:@"enableHrtf"];
|
||||
enableHeadTracking = [[[NSUserDefaultsController sharedUserDefaultsController] defaults] boolForKey:@"enableHeadTracking"];
|
||||
if(streamFormatStarted)
|
||||
resetStreamFormat = YES;
|
||||
} else if([keyPath isEqualToString:@"values.enableFSurround"]) {
|
||||
|
@ -793,12 +797,27 @@ current_device_listener(AudioObjectID inObjectID, UInt32 inNumberAddresses, cons
|
|||
rotationMatrixUpdated = NO;
|
||||
|
||||
simd_float4x4 matrix;
|
||||
if(!referenceMatrixSet) {
|
||||
if(!referenceMatrixSet || !enableHeadTracking) {
|
||||
referenceMatrixSet = NO;
|
||||
matrix = matrix_identity_float4x4;
|
||||
self->referenceMatrix = matrix;
|
||||
registerMotionListener(self);
|
||||
if(enableHeadTracking) {
|
||||
lastEnableHeadTracking = YES;
|
||||
registerMotionListener(self);
|
||||
} else if(lastEnableHeadTracking) {
|
||||
lastEnableHeadTracking = NO;
|
||||
unregisterMotionListener();
|
||||
}
|
||||
} else {
|
||||
matrix = simd_mul(rotationMatrix, referenceMatrix);
|
||||
simd_float4x4 mirrorTransform = {
|
||||
simd_make_float4(-1.0, 0.0, 0.0, 0.0),
|
||||
simd_make_float4(0.0, 1.0, 0.0, 0.0),
|
||||
simd_make_float4(0.0, 0.0, 1.0, 0.0),
|
||||
simd_make_float4(0.0, 0.0, 0.0, 1.0)
|
||||
};
|
||||
|
||||
matrix = simd_mul(mirrorTransform, rotationMatrix);
|
||||
matrix = simd_mul(matrix, referenceMatrix);
|
||||
}
|
||||
|
||||
[outputLock lock];
|
||||
|
@ -808,7 +827,10 @@ current_device_listener(AudioObjectID inObjectID, UInt32 inNumberAddresses, cons
|
|||
channels = 2;
|
||||
channelConfig = AudioChannelSideLeft | AudioChannelSideRight;
|
||||
} else {
|
||||
unregisterMotionListener();
|
||||
if(lastEnableHeadTracking) {
|
||||
lastEnableHeadTracking = NO;
|
||||
unregisterMotionListener();
|
||||
}
|
||||
referenceMatrixSet = NO;
|
||||
|
||||
[outputLock lock];
|
||||
|
@ -976,7 +998,7 @@ current_device_listener(AudioObjectID inObjectID, UInt32 inNumberAddresses, cons
|
|||
int simpleSpeedInput = samplesRendered;
|
||||
int simpleSpeedRendered = 0;
|
||||
int channels = realStreamFormat.mChannelsPerFrame;
|
||||
size_t max_block_len = blockSize;
|
||||
//size_t max_block_len = blockSize;
|
||||
|
||||
if (fabs(pitch - lastPitch) > 1e-5 ||
|
||||
fabs(tempo - lastTempo) > 1e-5) {
|
||||
|
@ -1309,9 +1331,13 @@ current_device_listener(AudioObjectID inObjectID, UInt32 inNumberAddresses, cons
|
|||
[[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.GraphicEQenable" options:0 context:kOutputCoreAudioContext];
|
||||
[[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.eqPreamp" options:(NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew) context:kOutputCoreAudioContext];
|
||||
[[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.enableHrtf" options:(NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew) context:kOutputCoreAudioContext];
|
||||
[[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.enableHeadTracking" options:(NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew) context:kOutputCoreAudioContext];
|
||||
[[NSUserDefaultsController sharedUserDefaultsController] addObserver:self forKeyPath:@"values.enableFSurround" options:(NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew) context:kOutputCoreAudioContext];
|
||||
observersapplied = YES;
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(resetReferencePosition:) name:CogPlaybackDidResetHeadTracking object:nil];
|
||||
htlistenerapplied = YES;
|
||||
|
||||
bzero(&timeStamp, sizeof(timeStamp));
|
||||
timeStamp.mFlags = kAudioTimeStampSampleTimeValid;
|
||||
|
||||
|
@ -1381,14 +1407,20 @@ current_device_listener(AudioObjectID inObjectID, UInt32 inNumberAddresses, cons
|
|||
}
|
||||
@synchronized(self) {
|
||||
stopInvoked = YES;
|
||||
if(hrtf) {
|
||||
if(hrtf && lastEnableHeadTracking) {
|
||||
lastEnableHeadTracking = NO;
|
||||
unregisterMotionListener();
|
||||
}
|
||||
if(htlistenerapplied) {
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self name:CogPlaybackDidResetHeadTracking object:nil];
|
||||
htlistenerapplied = NO;
|
||||
}
|
||||
if(observersapplied) {
|
||||
[[NSUserDefaultsController sharedUserDefaultsController] removeObserver:self forKeyPath:@"values.outputDevice" context:kOutputCoreAudioContext];
|
||||
[[NSUserDefaultsController sharedUserDefaultsController] removeObserver:self forKeyPath:@"values.GraphicEQenable" context:kOutputCoreAudioContext];
|
||||
[[NSUserDefaultsController sharedUserDefaultsController] removeObserver:self forKeyPath:@"values.eqPreamp" context:kOutputCoreAudioContext];
|
||||
[[NSUserDefaultsController sharedUserDefaultsController] removeObserver:self forKeyPath:@"values.enableHrtf" context:kOutputCoreAudioContext];
|
||||
[[NSUserDefaultsController sharedUserDefaultsController] removeObserver:self forKeyPath:@"values.enableHeadTracking" context:kOutputCoreAudioContext];
|
||||
[[NSUserDefaultsController sharedUserDefaultsController] removeObserver:self forKeyPath:@"values.enableFSurround" context:kOutputCoreAudioContext];
|
||||
observersapplied = NO;
|
||||
}
|
||||
|
@ -1505,4 +1537,8 @@ current_device_listener(AudioObjectID inObjectID, UInt32 inNumberAddresses, cons
|
|||
rotationMatrixUpdated = YES;
|
||||
}
|
||||
|
||||
- (void)resetReferencePosition:(NSNotification *)notification {
|
||||
referenceMatrixSet = NO;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -251,6 +251,8 @@
|
|||
<userDefaultsController representsSharedInstance="YES" id="52" userLabel="Shared Defaults"/>
|
||||
<customObject id="57" userLabel="OutputPane" customClass="OutputPane">
|
||||
<connections>
|
||||
<outlet property="headRecenter" destination="BBu-91-qdU" id="zg0-q7-dpf"/>
|
||||
<outlet property="headTracking" destination="mz3-1e-AVD" id="vH2-Wq-sdT"/>
|
||||
<outlet property="outputDevices" destination="59" id="76"/>
|
||||
<outlet property="view" destination="58" id="73"/>
|
||||
</connections>
|
||||
|
@ -293,7 +295,7 @@
|
|||
</connections>
|
||||
</button>
|
||||
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="rG5-80-FId">
|
||||
<rect key="frame" x="18" y="80" width="602" height="18"/>
|
||||
<rect key="frame" x="18" y="80" width="200" height="18"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="check" title="Enable HRTF filter" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="NGx-0c-WVR">
|
||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||
|
@ -303,6 +305,28 @@
|
|||
<binding destination="52" name="value" keyPath="values.enableHrtf" id="BD0-cP-SfB"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="mz3-1e-AVD" userLabel="Head Tracking">
|
||||
<rect key="frame" x="224" y="80" width="184" height="18"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="check" title="Head Tracking" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="Lpr-85-geO" userLabel="Head Tracking">
|
||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<binding destination="52" name="value" keyPath="values.enableHeadTracking" id="XCn-hn-2n4"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="BBu-91-qdU" userLabel="Recenter button">
|
||||
<rect key="frame" x="450" y="72" width="89" height="32"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="push" title="Recenter" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="aQP-kn-fMB">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
<connections>
|
||||
<action selector="resetHeadTracking:" target="57" id="0KV-Tf-z7V"/>
|
||||
</connections>
|
||||
</buttonCell>
|
||||
</button>
|
||||
<textField focusRingType="none" verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="65">
|
||||
<rect key="frame" x="6" y="53" width="134" height="17"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
|
|
|
@ -12,8 +12,11 @@
|
|||
|
||||
@interface OutputPane : GeneralPreferencePane {
|
||||
IBOutlet OutputsArrayController *outputDevices;
|
||||
IBOutlet NSButton *headTracking;
|
||||
IBOutlet NSButton *headRecenter;
|
||||
}
|
||||
|
||||
- (IBAction)takeDeviceID:(id)sender;
|
||||
- (IBAction)resetHeadTracking:(id)sender;
|
||||
|
||||
@end
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
|
||||
#import "OutputPane.h"
|
||||
|
||||
static NSString *CogPlaybackDidResetHeadTracking = @"CogPlaybackDigResetHeadTracking";
|
||||
|
||||
@implementation OutputPane
|
||||
|
||||
- (NSString *)title {
|
||||
|
@ -15,6 +17,12 @@
|
|||
}
|
||||
|
||||
- (NSImage *)icon {
|
||||
if(@available(macOS 14.0, *)) {
|
||||
/* do nothing */
|
||||
} else {
|
||||
[headTracking setHidden:YES];
|
||||
[headRecenter setHidden:YES];
|
||||
}
|
||||
if(@available(macOS 11.0, *))
|
||||
return [NSImage imageWithSystemSymbolName:@"hifispeaker.2.fill" accessibilityDescription:nil];
|
||||
return [[NSImage alloc] initWithContentsOfFile:[[NSBundle bundleForClass:[self class]] pathForImageResource:@"output"]];
|
||||
|
@ -25,4 +33,8 @@
|
|||
[[NSUserDefaults standardUserDefaults] setObject:device forKey:@"outputDevice"];
|
||||
}
|
||||
|
||||
- (IBAction)resetHeadTracking:(id)sender {
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:CogPlaybackDidResetHeadTracking object:nil];
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -233,6 +233,12 @@
|
|||
/* Class = "NSButtonCell"; title = "Enable HRTF filter"; ObjectID = "NGx-0c-WVR"; */
|
||||
"NGx-0c-WVR.title" = "Enable HRTF filter";
|
||||
|
||||
/* Class = "NSButtonCell"; title = "Head Tracking"; ObjectID = "Lpr-85-geO"; */
|
||||
"Lpr-85-geO.title" = "Head Tracking";
|
||||
|
||||
/* Class = "NSButtonCell"; title = "Recenter"; ObjectID = "aQP-kn-fMB"; */
|
||||
"aQP-kn-fMB.title" = "Recenter";
|
||||
|
||||
/* Class = "NSButtonCell"; title = "Enable FreeSurround stereo to surround upmixing"; ObjectID = "F0i-UK-6Nu"; */
|
||||
"F0i-UK-6Nu.title" = "Enable FreeSurround stereo to surround upmixing";
|
||||
|
||||
|
|
|
@ -229,6 +229,12 @@
|
|||
/* Class = "NSButtonCell"; title = "Enable HRTF filter"; ObjectID = "NGx-0c-WVR"; */
|
||||
"NGx-0c-WVR.title" = "Activar filtro HRTF";
|
||||
|
||||
/* Class = "NSButtonCell"; title = "Head Tracking"; ObjectID = "Lpr-85-geO"; */
|
||||
"Lpr-85-geO.title" = "Seguimiento de cabeza";
|
||||
|
||||
/* Class = "NSButtonCell"; title = "Recenter"; ObjectID = "aQP-kn-fMB"; */
|
||||
"aQP-kn-fMB.title" = "Recalibrar";
|
||||
|
||||
/* Class = "NSButtonCell"; title = "Automatically check for updates on startup"; ObjectID = "207"; */
|
||||
"207.title" = "Buscar actualizaciones al abrir";
|
||||
|
||||
|
|
|
@ -194,6 +194,12 @@
|
|||
/* Class = "NSButtonCell"; title = "Enable HRTF filter"; ObjectID = "NGx-0c-WVR"; */
|
||||
"NGx-0c-WVR.title" = "Включить фильтр HRTF";
|
||||
|
||||
/* Class = "NSButtonCell"; title = "Head Tracking"; ObjectID = "Lpr-85-geO"; */
|
||||
"Lpr-85-geO.title" = "Трекинг головы";
|
||||
|
||||
/* Class = "NSButtonCell"; title = "Recenter"; ObjectID = "aQP-kn-fMB"; */
|
||||
"aQP-kn-fMB.title" = "Перецентрировать";
|
||||
|
||||
/* Class = "NSButtonCell"; title = "Enable FreeSurround stereo to surround upmixing"; ObjectID = "F0i-UK-6Nu"; */
|
||||
"F0i-UK-6Nu.title" = "Включить FreeSurround апмикс стерео в объемный звук";
|
||||
|
||||
|
|
|
@ -131,6 +131,12 @@
|
|||
/* Class = "NSButtonCell"; title = "Enable HRTF filter"; ObjectID = "NGx-0c-WVR"; */
|
||||
"NGx-0c-WVR.title" = "HRTF filtresini etkinleştir";
|
||||
|
||||
/* Class = "NSButtonCell"; title = "Head Tracking"; ObjectID = "Lpr-85-geO"; */
|
||||
"Lpr-85-geO.title" = "Kafa Takibi";
|
||||
|
||||
/* Class = "NSButtonCell"; title = "Recenter"; ObjectID = "aQP-kn-fMB"; */
|
||||
"aQP-kn-fMB.title" = "Yeniden Merkeze Getir";
|
||||
|
||||
/* Class = "NSButtonCell"; title = "Use 3D rendered spectrum"; ObjectID = "NMg-TO-amV"; */
|
||||
"NMg-TO-amV.title" = "3D işlenmiş spektrum kullanın";
|
||||
|
||||
|
|
Loading…
Reference in a new issue